{"TotalCount":41,"Files":[{"Ident":"verarp.colour_break","Path":"styles/form/_switch.scss","FileName":"_switch.scss","PackageType":"game","CodeKind":"Game","AssetVersionId":292528,"IsPrivate":false,"Code":"\r\n$primary: red !default;\r\n$primary-alt: white !default;\r\n\r\n$switch-padding: 6px !default;\r\n\r\n.checkbox.switch\r\n{\r\n\tcursor: pointer;\r\n\r\n\t\u003E .checkmark\r\n\t{\r\n\t\tfont-size: 22px;\r\n\t\tborder: 0px solid $primary;\r\n\t\tborder-radius: 100px;\r\n\t\ttext-align: center;\r\n\t\tjustify-content: center;\r\n\t\talign-items: center;\r\n\t\tcolor: $primary-alt;\r\n\t\tpadding: $switch-padding;\r\n\t\tpadding-right: 32px;\r\n\t\tpadding-left: $switch-padding;\r\n\t\ttransition: all 0.3s ease;\r\n\t\tbackground-color: rgba( $primary, 0.1 );\r\n\r\n\t\t\u003E .handle\r\n\t\t{\r\n\t\t\tbackground-color: $primary-alt;\r\n\t\t\twidth: 20px;\r\n\t\t\theight: 20px;\r\n\t\t\tborder-radius: 100px;\r\n\t\t\tbox-shadow: 2px 2px 12px black;\r\n\t\t}\r\n\t}\r\n\r\n\t\u0026.checked\r\n\t{\r\n\t\t\u003E .checkmark\r\n\t\t{\r\n\t\t\tbackground-color: $primary;\r\n\t\t\tpadding-left: 32px;\r\n\t\t\tpadding-right: $switch-padding;\r\n\t\t}\r\n\t}\r\n\r\n\t\u0026:active\r\n\t{\r\n\t\ttransform: scale( 0.9 );\r\n\t\ttransform-origin: 20px 50%;\r\n\t}\r\n}\r\n"},{"Ident":"verarp.colour_break","Path":"ui/controls/slidercontrol.razor.scss","FileName":"slidercontrol.razor.scss","PackageType":"game","CodeKind":"Game","AssetVersionId":292528,"IsPrivate":false,"Code":"\r\n.slidercontrol\r\n{\r\n    flex-direction: row;\r\n    min-width: 50px;\r\n    position: relative;\r\n    flex-shrink: 0;\r\n    flex-direction: row;\r\n    cursor: pointer;\r\n    gap: 8px;\r\n    flex-grow: 1;\r\n    align-items: center;\r\n    pointer-events: all;\r\n\r\n    \u003E .inner\r\n    {\r\n        flex-direction: column;\r\n        flex-shrink: 1;\r\n        flex-grow: 1;\r\n        min-height: 32px;\r\n        justify-content: center;\r\n\r\n        \u003E .values\r\n        {\r\n            width: 100%;\r\n            pointer-events: none;\r\n            font-size: 14px;\r\n            color: #aaa;\r\n\r\n            \u003E .left\r\n            {\r\n                flex-grow: 1;\r\n            }\r\n        }\r\n\r\n        \u003E .track\r\n        {\r\n            position: relative;\r\n            background-color: #888;\r\n            height: 7px;\r\n            margin: 8px;\r\n            align-items: center;\r\n            border-radius: 4px;\r\n\r\n            \u003E .track-active\r\n            {\r\n                background-color: #fff;\r\n                position: absolute;\r\n                height: 100%;\r\n                left: 0px;\r\n                border-radius: 4px;\r\n            }\r\n\r\n            \u003E .thumb\r\n            {\r\n                position: relative;\r\n                background-color: #fff;\r\n                border-radius: 100px;\r\n                width: 16px;\r\n                height: 16px;\r\n                transform: translateX( -50% );\r\n            }\r\n        }\r\n    }\r\n\r\n    \u003E .entry\r\n    {\r\n        flex-shrink: 0;\r\n        flex-grow: 0;\r\n        width: 50px;\r\n\r\n        \u003E numberentry\r\n        {\r\n            background-color: transparent;\r\n\r\n            \u003E .content-label\r\n            {\r\n                padding: 0 4px;\r\n            }\r\n        }\r\n    }\r\n}\r\n\r\n\r\n.slidercontrol .value-tooltip\r\n{\r\n    position: absolute;\r\n    bottom: 150%;\r\n    left: -8px;\r\n    z-index: 1000;\r\n    flex-direction: column;\r\n\r\n    \u003E .label\r\n    {       \r\n        background-color: black;\r\n        padding: 8px 12px;\r\n        border-radius: 8px;\r\n    }\r\n\r\n    \u003E.tail\r\n    {\r\n        bottom: -0px;\r\n        background-color: black;\r\n        width: 10px;\r\n        height: 10px;\r\n        transform: rotateZ(45 deg) translateX( 4px );\r\n        position: absolute;\r\n    }\r\n}"},{"Ident":"verarp.colour_break","Path":"ui/controls/color/coloralphacontrol.cs.scss","FileName":"coloralphacontrol.cs.scss","PackageType":"game","CodeKind":"Game","AssetVersionId":292528,"IsPrivate":false,"Code":"ColorAlphaControl\r\n{\r\n\tgap: 0.5rem;\r\n\tflex-grow: 1;\r\n\tpointer-events: all;\r\n\tbackground: linear-gradient( to right, black, white );\r\n\tborder-radius: 4px;\r\n\tpadding: 2px;\r\n\theight: 12px;\r\n\tposition: relative;\r\n\tcursor: pointer;\r\n\tborder: 1px solid #333;\r\n\r\n\t\u0026:hover\r\n\t{\r\n\t\tborder: 1px solid #08f;\r\n\t}\r\n\r\n\t\u0026:active\r\n\t{\r\n\t\tborder: 1px solid #fff;\r\n\t}\r\n\r\n\t.handle\r\n\t{\r\n\t\ttop: -5px;\r\n\t\tbottom: -5px;\r\n\t\taspect-ratio: 1;\r\n\t\tborder-radius: 100px;\r\n\t\tborder: 2px solid #444;\r\n\t\tposition: absolute;\r\n\t\tbackground-color: white;\r\n\t\tbox-shadow: 2px 2px 16px #000a;\r\n\t\ttransform: translateX( -50% );\r\n\t\tpointer-events: none;\r\n\t}\r\n}\r\n"},{"Ident":"verarp.colour_break","Path":"styles/rootpanel.scss","FileName":"rootpanel.scss","PackageType":"game","CodeKind":"Game","AssetVersionId":292528,"IsPrivate":false,"Code":"\r\n\r\nRootPanel\r\n{\r\n\tfont-family: Roboto;\r\n\tcolor: white;\r\n}\r\n\r\nIconPanel, i\r\n{\r\n\tfont-family: Material Icons;\r\n\tbackground-position: center;\r\n\tbackground-size: contain;\r\n}\r\n\r\n.tooltip\r\n{\r\n\tbackground-color: rgba( black, 0.8 );\r\n\tborder: 1px solid rgba( #555, 0.1 );\r\n\tpadding: 10px;\r\n\tborder-radius: 4px;\r\n\tcolor: white;\r\n\tfont-family: Inter;\r\n\tfont-weight: bold;\r\n\ttransition: opacity 0.09s ease;\r\n\topacity: 1;\r\n\tmargin: 0px;\r\n\r\n\t\u0026:intro, \u0026:outro\r\n\t{\r\n\t\topacity: 0;\r\n\t}\r\n}\r\n\r\n.textentry\r\n{\r\n\tcursor: text;\r\n\talign-items: center;\r\n\tjustify-content: center;\r\n\twhite-space: nowrap;\r\n\toverflow: hidden;\r\n\tflex-direction: row;\r\n\tposition: relative;\r\n\tpadding: 10px;\r\n\r\n\t\u0026.disabled\r\n\t{\r\n\t\tcursor: default;\r\n\t}\r\n\r\n\t\u0026.is-multiline\r\n\t{\r\n\t\talign-items: flex-start;\r\n\t\twhite-space: normal;\r\n\t}\r\n\r\n\t.content-label,\r\n\t.placeholder\r\n\t{\r\n\t\tflex-grow: 1;\r\n\t}\r\n\r\n\t.placeholder\r\n\t{\r\n\t\topacity: 0.2;\r\n\t\tpointer-events: none;\r\n\t}\r\n\r\n\t.iconpanel\r\n\t{\r\n\t\tposition: absolute;\r\n\t\tright: 0;\r\n\t\tpadding-right: 10px;\r\n\t\tpointer-events: none;\r\n\r\n\t\t\u0026.clearbutton\r\n\t\t{\r\n\t\t\tcolor: #fff;\r\n\t\t\tpointer-events: all;\r\n\t\t\tcursor: pointer;\r\n\t\t\topacity: 0.1;\r\n\r\n\t\t\t\u0026:hover\r\n\t\t\t{\r\n\t\t\t\topacity: 0.5;\r\n\t\t\t}\r\n\r\n\t\t\t\u0026:active\r\n\t\t\t{\r\n\t\t\t\topacity: 1;\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\r\n\t\u0026:empty\r\n\t{\r\n\t\t.clearbutton\r\n\t\t{\r\n\t\t\tdisplay: none;\r\n\t\t}\r\n\t}\r\n\r\n\t\u0026.has-icon\r\n\t{\r\n\t\tpadding-right: 30px;\r\n\t}\r\n\r\n\t.content-label,\r\n\t.prefix-label,\r\n\t.suffix-label,\r\n\t.placeholder\r\n\t{\r\n\t\toverflow: hidden;\r\n\t}\r\n\r\n\t.content-label\r\n\t{\r\n\t\torder: 1;\r\n\t}\r\n\r\n\t.suffix-label\r\n\t{\r\n\t\torder: 2;\r\n\t}\r\n\r\n\t.prefix-label,\r\n\t.suffix-label\r\n\t{\r\n\t\tflex-shrink: 0;\r\n\t\topacity: 0.5;\r\n\t}\r\n\r\n\t\u0026.invalid\r\n\t{\r\n\t\tbox-shadow: 0px 0px 1px 2px #f8356b;\r\n\t}\r\n}\r\n\r\n.popup-panel\r\n{\r\n\tbackground-color: #1b202c;\r\n\tflex-direction: column;\r\n\tcolor: #8e9ec2;\r\n\ttransition: all 0.1s ease-out;\r\n\tposition: absolute;\r\n\tz-index: 2000;\r\n\tmin-height: 20px;\r\n\tmin-width: 10px;\r\n\toverflow: scroll;\r\n\tpointer-events: all;\r\n\tbox-shadow: 3px 3px 64px #000;\r\n\tborder-radius: 4px;\r\n\r\n\t\u0026.medium\r\n\t{\r\n\t\tmax-width: 300px;\r\n\t}\r\n\r\n\t\u0026.center-horizontal\r\n\t{\r\n\t\ttransform-origin: top center;\r\n\t}\r\n\r\n\t\u0026.below-center\r\n\t{\r\n\t\ttransform: translateX( -50% );\r\n\t\ttransform-origin: 0% 0%;\r\n\t}\r\n\r\n\t\u0026.above-left\r\n\t{\r\n\t\ttransform-origin: 0% 100%;\r\n\t}\r\n\r\n\t\u0026.above-center\r\n\t{\r\n\t\ttransform: translateX( -50% );\r\n\t\ttransform-origin: 0% 100%;\r\n\t}\r\n\r\n\t\u0026.left\r\n\t{\r\n\t\ttransform-origin: 100% 50%;\r\n\t\ttransform: translate( 00% -50% );\r\n\t}\r\n\r\n\t\u0026.right\r\n\t{\r\n\t\ttransform-origin: 0 50%;\r\n\t\ttransform: translate( 0% -50% );\r\n\t}\r\n\r\n\t\u0026:intro\r\n\t{\r\n\t\ttransform: scale( 0 );\r\n\t\tpointer-events: none;\r\n\t\topacity: 0;\r\n\t}\r\n\r\n\t\u0026:outro\r\n\t{\r\n\t\topacity: 0;\r\n\t\ttransition: all 0.1s ease-in;\r\n\t\tmargin-top: 50px;\r\n\t\tpointer-events: none;\r\n\t}\r\n\r\n\t\u0026.below-stretch\r\n\t{\r\n\t\ttransform-origin: 0% 0%;\r\n\r\n\t\t\u0026:intro\r\n\t\t{\r\n\t\t\ttransform: scaleY( 0.1 );\r\n\t\t}\r\n\t}\r\n\r\n\t\u003E .canvas\r\n\t{\r\n\t\tflex-direction: column;\r\n\t}\r\n\r\n\t.information\r\n\t{\r\n\t\tpadding: 16px;\r\n\t\tfont-size: 14px;\r\n\t\topacity: 0.5;\r\n\t}\r\n\r\n\tbutton\r\n\t{\r\n\t\tpadding: 2px 8px;\r\n\t\tcursor: pointer;\r\n\t\tfont-family: Poppins;\r\n\t\tfont-weight: 600;\r\n\t\tflex-shrink: 0;\r\n\r\n\t\t\u0026:hover\r\n\t\t{\r\n\t\t\tbackground-color: #08f;\r\n\t\t\tcolor: #fff;\r\n\t\t}\r\n\t}\r\n}\r\n"},{"Ident":"verarp.colour_break","Path":"colourbreakmenu.razor.scss","FileName":"colourbreakmenu.razor.scss","PackageType":"game","CodeKind":"Game","AssetVersionId":292528,"IsPrivate":false,"Code":".cb-ui {\n    position: absolute;\n    inset: 0px;\n    width: 100%;\n    height: 100%;\n    font-family: \u0022Inter\u0022, \u0022Poppins\u0022, \u0022Segoe UI\u0022, sans-serif;\n    color: #ffffff;\n    pointer-events: none;\n}\n\n.cb-loading {\n    position: absolute;\n    top: 24px;\n    left: 24px;\n    padding: 10px 14px;\n    font-size: 18px;\n    font-weight: 800;\n    color: #ffffff;\n    background-color: rgba(5, 8, 20, 0.88);\n    border: 1px solid rgba(255, 255, 255, 0.18);\n    border-radius: 8px;\n}\n\n.cb-screen {\n    position: absolute;\n    inset: 0px;\n    width: 100%;\n    height: 100%;\n    display: flex;\n    flex-direction: column;\n    align-items: center;\n    justify-content: center;\n    gap: 28px;\n    pointer-events: all;\n    background-color: rgba(4, 6, 16, 0.70);\n}\n\n.cb-main {\n    justify-content: flex-start;\n    gap: 0px;\n    padding: 24px 30px 28px;\n    background-color: rgba(5, 7, 18, 0.18);\n}\n\n.cb-menu-top {\n    width: 100%;\n    display: flex;\n    flex-direction: row;\n    align-items: flex-start;\n    justify-content: space-between;\n    gap: 24px;\n}\n\n.cb-menu-metrics {\n    display: flex;\n    flex-direction: row;\n    gap: 10px;\n}\n\n.cb-menu-metric {\n    min-width: 98px;\n    padding: 8px 12px;\n    display: flex;\n    flex-direction: column;\n    align-items: flex-start;\n    background-color: rgba(4, 8, 20, 0.84);\n    border: 1px solid rgba(255, 255, 255, 0.20);\n    border-radius: 8px;\n    box-shadow: 0px 10px 24px rgba(0, 0, 0, 0.38);\n\n    span {\n        font-size: 12px;\n        font-weight: 900;\n        text-transform: uppercase;\n        color: #aeefff;\n    }\n\n    b {\n        margin-top: -2px;\n        font-size: 28px;\n        line-height: 30px;\n        font-weight: 900;\n        color: #ffffff;\n        text-shadow: 0px 3px 6px rgba(0, 0, 0, 0.90);\n    }\n}\n\n.cb-menu-actions {\n    pointer-events: all;\n    margin-top: auto;\n    display: flex;\n    flex-direction: row;\n    justify-content: center;\n    gap: 12px;\n    width: auto;\n    padding: 12px;\n    background-color: rgba(4, 8, 20, 0.84);\n    border: 1px solid rgba(255, 255, 255, 0.18);\n    border-radius: 8px;\n    box-shadow: 0px 16px 42px rgba(0, 0, 0, 0.50);\n\n    .cb-btn {\n        width: 178px;\n    }\n}\n\n.cb-level-select {\n    pointer-events: all;\n    margin-top: 4px;\n    display: flex;\n    flex-direction: row;\n    align-items: center;\n    justify-content: center;\n    gap: 12px;\n    width: 398px;\n    padding: 10px 12px;\n    background-color: rgba(4, 8, 20, 0.82);\n    border: 1px solid rgba(255, 255, 255, 0.16);\n    border-radius: 8px;\n    box-shadow: 0px 14px 36px rgba(0, 0, 0, 0.42);\n}\n\n.cb-level-nav {\n    width: 48px;\n    height: 46px;\n    display: flex;\n    align-items: center;\n    justify-content: center;\n    font-size: 28px;\n    line-height: 28px;\n    font-weight: 900;\n    color: #07111a;\n    background-color: #aeefff;\n    border: 2px solid rgba(255, 255, 255, 0.82);\n    border-radius: 8px;\n    box-shadow: 0px 0px 16px rgba(92, 237, 255, 0.46);\n    cursor: pointer;\n    transition: all 0.10s ease-out;\n\n    \u0026:hover {\n        transform: scale(1.04);\n        border-color: #ffffff;\n    }\n\n    \u0026:active {\n        transform: scale(0.97);\n    }\n\n    \u0026.disabled {\n        color: rgba(255, 255, 255, 0.34);\n        background-color: rgba(255, 255, 255, 0.06);\n        border-color: rgba(255, 255, 255, 0.12);\n        box-shadow: none;\n    }\n}\n\n.cb-level-select-copy {\n    width: 262px;\n    display: flex;\n    flex-direction: column;\n    align-items: center;\n\n    span {\n        font-size: 12px;\n        font-weight: 900;\n        text-transform: uppercase;\n        color: #aeefff;\n        text-shadow: 0px 2px 3px rgba(0, 0, 0, 1);\n    }\n\n    b {\n        margin-top: -1px;\n        font-size: 19px;\n        line-height: 22px;\n        font-weight: 900;\n        color: #ffffff;\n        text-align: center;\n        text-shadow: 0px 3px 5px rgba(0, 0, 0, 1);\n    }\n}\n\n.cb-title-wrap {\n    display: flex;\n    flex-direction: column;\n    align-items: flex-start;\n    gap: 4px;\n}\n\n.cb-mode-tabs {\n    display: flex;\n    flex-direction: row;\n    gap: 8px;\n    margin: 6px 0px 2px;\n    padding: 5px;\n    background-color: rgba(4, 8, 20, 0.78);\n    border: 1px solid rgba(255, 255, 255, 0.14);\n    border-radius: 10px;\n}\n\n.cb-mode-tab {\n    pointer-events: all;\n    width: 150px;\n    height: 42px;\n    display: flex;\n    align-items: center;\n    justify-content: center;\n    font-size: 17px;\n    font-weight: 900;\n    letter-spacing: 0px;\n    color: rgba(255, 255, 255, 0.66);\n    background-color: rgba(255, 255, 255, 0.05);\n    border: 2px solid rgba(255, 255, 255, 0.10);\n    border-radius: 8px;\n    cursor: pointer;\n    transition: all 0.10s ease-out;\n\n    \u0026:hover {\n        color: #ffffff;\n        border-color: rgba(92, 237, 255, 0.55);\n    }\n\n    \u0026.active {\n        color: #07111a;\n        background-color: #aeefff;\n        border-color: #ffffff;\n        box-shadow: 0px 0px 16px rgba(92, 237, 255, 0.55);\n    }\n}\n\n.cb-record-row {\n    color: #07111a;\n    background-color: #ffd23f;\n    border-radius: 6px;\n\n    span {\n        color: #07111a;\n    }\n\n    b {\n        color: #07111a;\n    }\n}\n\n.cb-title {\n    margin: 0px;\n    font-size: 62px;\n    line-height: 64px;\n    font-weight: 900;\n    letter-spacing: 0px;\n    color: #ffffff;\n    text-shadow:\n        0px 4px 0px rgba(20, 224, 255, 0.85),\n        0px 10px 0px rgba(199, 56, 255, 0.55),\n        0px 22px 42px rgba(0, 0, 0, 0.75);\n}\n\n.cb-tagline {\n    margin: 0px;\n    padding: 7px 12px;\n    font-size: 16px;\n    font-weight: 800;\n    color: #f4fbff;\n    background-color: rgba(4, 8, 20, 0.78);\n    border: 1px solid rgba(255, 255, 255, 0.16);\n    border-radius: 8px;\n    text-shadow: 0px 2px 4px rgba(0, 0, 0, 0.9);\n}\n\n.cb-level-brief {\n    max-width: 520px;\n    margin: 0px;\n    padding: 8px 12px;\n    font-size: 15px;\n    line-height: 19px;\n    font-weight: 800;\n    color: rgba(255, 255, 255, 0.88);\n    background-color: rgba(4, 8, 20, 0.66);\n    border: 1px solid rgba(255, 255, 255, 0.12);\n    border-radius: 8px;\n    text-shadow: 0px 2px 4px rgba(0, 0, 0, 0.95);\n}\n\n.cb-level-objective {\n    max-width: 520px;\n    margin: 0px;\n    padding: 7px 12px;\n    font-size: 15px;\n    line-height: 18px;\n    font-weight: 900;\n    color: #07111a;\n    background-color: #aeefff;\n    border: 1px solid rgba(255, 255, 255, 0.85);\n    border-radius: 8px;\n    box-shadow: 0px 0px 18px rgba(92, 237, 255, 0.38);\n}\n\n.cb-level-rail {\n    display: flex;\n    flex-direction: row;\n    align-items: center;\n    gap: 7px;\n    margin-top: 4px;\n    padding: 6px 8px;\n    background-color: rgba(4, 8, 20, 0.58);\n    border: 1px solid rgba(255, 255, 255, 0.12);\n    border-radius: 8px;\n}\n\n.cb-level-pip {\n    min-width: 28px;\n    height: 28px;\n    padding: 0px 7px;\n    display: flex;\n    align-items: center;\n    justify-content: center;\n    font-size: 14px;\n    font-weight: 900;\n    color: rgba(255, 255, 255, 0.54);\n    background-color: rgba(255, 255, 255, 0.08);\n    border: 1px solid rgba(255, 255, 255, 0.14);\n    border-radius: 8px;\n    text-shadow: 0px 2px 4px rgba(0, 0, 0, 0.90);\n\n    \u0026.complete {\n        color: #04120b;\n        background-color: rgba(66, 247, 123, 0.92);\n        border-color: rgba(196, 255, 214, 0.95);\n        text-shadow: none;\n    }\n\n    \u0026.active {\n        color: #07111a;\n        background-color: #aeefff;\n        border-color: #ffffff;\n        box-shadow: 0px 0px 18px rgba(92, 237, 255, 0.80);\n        text-shadow: none;\n    }\n\n    \u0026.locked {\n        color: rgba(255, 255, 255, 0.36);\n        background-color: rgba(255, 255, 255, 0.04);\n        border-color: rgba(255, 255, 255, 0.08);\n    }\n}\n\n.cb-buttons {\n    display: flex;\n    flex-direction: column;\n    align-items: center;\n    gap: 12px;\n    width: 320px;\n}\n\n.cb-btn {\n    pointer-events: all;\n    width: 100%;\n    height: 58px;\n    display: flex;\n    align-items: center;\n    justify-content: center;\n    font-size: 22px;\n    font-weight: 900;\n    letter-spacing: 0px;\n    color: #ffffff;\n    background-color: rgba(11, 16, 32, 0.90);\n    border: 2px solid rgba(255, 255, 255, 0.22);\n    border-radius: 8px;\n    box-shadow: 0px 12px 28px rgba(0, 0, 0, 0.40);\n    transition: all 0.10s ease-out;\n    cursor: pointer;\n\n    \u0026:hover {\n        background-color: rgba(25, 36, 64, 0.96);\n        border-color: rgba(255, 255, 255, 0.70);\n        transform: scale(1.035);\n    }\n\n    \u0026:active {\n        transform: scale(0.98);\n    }\n}\n\n.cb-primary {\n    color: #04120b;\n    background-color: #42f77b;\n    border-color: #c4ffd6;\n    text-shadow: none;\n\n    \u0026:hover {\n        background-color: #6dff98;\n        border-color: #ffffff;\n    }\n}\n\n.cb-disabled {\n    color: rgba(255, 255, 255, 0.42);\n    background-color: rgba(255, 255, 255, 0.07);\n    border-color: rgba(255, 255, 255, 0.14);\n    box-shadow: none;\n\n    \u0026:hover {\n        background-color: rgba(255, 255, 255, 0.08);\n        border-color: rgba(255, 255, 255, 0.18);\n        transform: none;\n    }\n}\n\n.cb-hint {\n    position: absolute;\n    bottom: 30px;\n    left: 0px;\n    right: 0px;\n    align-self: center;\n    width: 620px;\n    margin: 0px auto;\n    padding: 11px 18px;\n    justify-content: center;\n    text-align: center;\n    font-size: 16px;\n    font-weight: 800;\n    color: #f4fbff;\n    background-color: rgba(4, 8, 20, 0.82);\n    border: 1px solid rgba(92, 237, 255, 0.45);\n    border-radius: 10px;\n    box-shadow: 0px 10px 28px rgba(0, 0, 0, 0.50);\n    text-shadow: 0px 2px 4px rgba(0, 0, 0, 0.95);\n}\n\n.cb-hint-stuck {\n    color: #07111a;\n    background-color: #aeefff;\n    border-color: #ffffff;\n    box-shadow: 0px 0px 22px rgba(92, 237, 255, 0.55);\n    text-shadow: none;\n}\n\n.cb-panel {\n    display: flex;\n    flex-direction: column;\n    align-items: center;\n    gap: 22px;\n    padding: 38px 48px;\n    min-width: 380px;\n    background-color: rgba(5, 8, 22, 0.94);\n    border: 2px solid rgba(92, 237, 255, 0.42);\n    border-radius: 8px;\n    box-shadow: 0px 22px 70px rgba(0, 0, 0, 0.72);\n}\n\n.cb-settings-screen {\n    z-index: 50;\n    background-color: rgba(3, 5, 14, 0.94);\n}\n\n.cb-settings-panel {\n    z-index: 51;\n    min-width: 420px;\n    background-color: rgba(5, 8, 22, 0.98);\n}\n\n.cb-settings-panel .cb-panel-title {\n    font-size: 40px;\n}\n\n.cb-setting-row {\n    pointer-events: all;\n    display: flex;\n    flex-direction: row;\n    align-items: center;\n    justify-content: space-between;\n    gap: 24px;\n    width: 100%;\n    min-height: 52px;\n    padding: 10px 14px;\n    color: rgba(255, 255, 255, 0.82);\n    background-color: rgba(255, 255, 255, 0.06);\n    border: 1px solid rgba(255, 255, 255, 0.12);\n    border-radius: 6px;\n    font-size: 17px;\n    font-weight: 900;\n    cursor: pointer;\n\n    b {\n        color: #42f77b;\n        font-size: 18px;\n    }\n\n    \u0026:hover {\n        background-color: rgba(66, 247, 123, 0.16);\n        border-color: rgba(66, 247, 123, 0.72);\n    }\n\n    \u0026.focused {\n        color: #ffffff;\n        background-color: rgba(92, 237, 255, 0.18);\n        border-color: rgba(92, 237, 255, 0.92);\n        box-shadow: 0px 0px 18px rgba(92, 237, 255, 0.42);\n    }\n}\n\n.cb-panel-title {\n    margin: 0px;\n    font-size: 46px;\n    font-weight: 900;\n    color: #ffffff;\n    text-shadow: 0px 5px 18px rgba(78, 226, 255, 0.65);\n}\n\n.cb-readout {\n    display: flex;\n    flex-direction: column;\n    gap: 8px;\n    width: 100%;\n}\n\n.cb-readout-row {\n    display: flex;\n    flex-direction: row;\n    align-items: center;\n    justify-content: space-between;\n    gap: 24px;\n    width: 100%;\n    padding: 9px 12px;\n    font-size: 17px;\n    font-weight: 800;\n    color: rgba(255, 255, 255, 0.68);\n    background-color: rgba(255, 255, 255, 0.06);\n    border-radius: 6px;\n\n    b {\n        color: #ffffff;\n        font-weight: 900;\n    }\n}\n\n.cb-hud {\n    position: absolute;\n    top: 20px;\n    left: 20px;\n    width: 300px;\n    display: flex;\n    flex-direction: column;\n    align-items: stretch;\n    gap: 8px;\n    pointer-events: none;\n}\n\n.cb-stat,\n.cb-status {\n    display: flex;\n    flex-direction: column;\n    justify-content: center;\n    width: 100%;\n    min-height: 58px;\n    padding: 8px 14px;\n    background-color: rgba(4, 7, 18, 0.92);\n    border: 2px solid rgba(255, 255, 255, 0.24);\n    border-radius: 8px;\n    box-shadow:\n        0px 10px 24px rgba(0, 0, 0, 0.45),\n        inset 0px 0px 18px rgba(58, 226, 255, 0.10);\n}\n\n.cb-stat-label,\n.cb-status-label {\n    font-size: 14px;\n    font-weight: 900;\n    text-transform: uppercase;\n    color: #aeefff;\n    text-shadow: 0px 2px 3px rgba(0, 0, 0, 1);\n}\n\n.cb-stat-value {\n    margin-top: -2px;\n    font-size: 32px;\n    line-height: 32px;\n    font-weight: 900;\n    color: #ffffff;\n    text-shadow: 0px 3px 5px rgba(0, 0, 0, 1);\n}\n\n.cb-stat-subtitle {\n    margin-top: 2px;\n    font-size: 14px;\n    line-height: 16px;\n    font-weight: 900;\n    color: rgba(255, 255, 255, 0.82);\n    text-shadow: 0px 2px 4px rgba(0, 0, 0, 1);\n}\n\n.cb-status {\n    min-width: 0px;\n}\n\n.cb-progress {\n    width: 100%;\n    min-height: 62px;\n    padding: 9px 14px;\n    display: flex;\n    flex-direction: column;\n    justify-content: center;\n    background-color: rgba(4, 7, 18, 0.92);\n    border: 2px solid rgba(255, 255, 255, 0.24);\n    border-radius: 8px;\n    box-shadow:\n        0px 10px 24px rgba(0, 0, 0, 0.45),\n        inset 0px 0px 18px rgba(66, 247, 123, 0.10);\n}\n\n.cb-progress-copy {\n    display: flex;\n    flex-direction: row;\n    align-items: center;\n    justify-content: space-between;\n    gap: 12px;\n\n    span {\n        font-size: 14px;\n        font-weight: 900;\n        text-transform: uppercase;\n        color: #aeefff;\n        text-shadow: 0px 2px 3px rgba(0, 0, 0, 1);\n    }\n\n    b {\n        font-size: 18px;\n        font-weight: 900;\n        color: #ffffff;\n        text-shadow: 0px 2px 3px rgba(0, 0, 0, 1);\n    }\n}\n\n.cb-progress-track {\n    width: 100%;\n    height: 10px;\n    margin-top: 7px;\n    background-color: rgba(255, 255, 255, 0.10);\n    border-radius: 5px;\n    overflow: hidden;\n}\n\n.cb-progress-fill {\n    height: 100%;\n    min-width: 3px;\n    background-color: #42f77b;\n    border-radius: 5px;\n    box-shadow: 0px 0px 18px rgba(66, 247, 123, 0.75);\n}\n\n.cb-objective {\n    box-shadow:\n        0px 10px 24px rgba(0, 0, 0, 0.45),\n        inset 0px 0px 18px rgba(92, 237, 255, 0.16);\n}\n\n.cb-objective-name {\n    margin-top: 2px;\n    font-size: 13px;\n    line-height: 15px;\n    font-weight: 900;\n    color: rgba(255, 255, 255, 0.86);\n    text-shadow: 0px 2px 3px rgba(0, 0, 0, 1);\n}\n\n.cb-objective-fill {\n    background-color: #aeefff;\n    box-shadow: 0px 0px 18px rgba(92, 237, 255, 0.82);\n}\n\n.cb-status-value {\n    margin-top: 2px;\n    font-size: 20px;\n    line-height: 22px;\n    font-weight: 900;\n    color: #ffffff;\n    text-shadow: 0px 3px 5px rgba(0, 0, 0, 1);\n}\n\n.cb-pause-btn {\n    position: absolute;\n    top: 20px;\n    right: 20px;\n    pointer-events: all;\n    width: 68px;\n    min-height: 68px;\n    display: flex;\n    align-items: center;\n    justify-content: center;\n    font-size: 24px;\n    font-weight: 900;\n    color: #ffffff;\n    background-color: rgba(4, 7, 18, 0.92);\n    border: 2px solid rgba(255, 255, 255, 0.30);\n    border-radius: 8px;\n    box-shadow: 0px 10px 24px rgba(0, 0, 0, 0.45);\n    cursor: pointer;\n    transition: all 0.10s ease-out;\n\n    \u0026:hover {\n        color: #04120b;\n        background-color: #42f77b;\n        border-color: #ffffff;\n        transform: scale(1.04);\n    }\n\n    \u0026:active {\n        transform: scale(0.97);\n    }\n}\n\n/* -------- bug reporting -------- */\n\n.cb-report-panel {\n    min-width: 520px;\n}\n\n.cb-report-intro {\n    margin: 0px;\n    max-width: 460px;\n    font-size: 15px;\n    line-height: 19px;\n    font-weight: 700;\n    text-align: center;\n    color: rgba(255, 255, 255, 0.82);\n    text-shadow: 0px 2px 4px rgba(0, 0, 0, 0.9);\n}\n\n.cb-report-input {\n    width: 460px;\n    height: 150px;\n    padding: 12px 14px;\n    font-size: 16px;\n    font-weight: 600;\n    color: #ffffff;\n    background-color: rgba(255, 255, 255, 0.06);\n    border: 2px solid rgba(92, 237, 255, 0.45);\n    border-radius: 8px;\n\n    \u0026:focus {\n        border-color: #aeefff;\n        background-color: rgba(255, 255, 255, 0.10);\n    }\n}\n\n.cb-report-feedback {\n    width: 460px;\n    padding: 8px 12px;\n    font-size: 15px;\n    font-weight: 800;\n    text-align: center;\n    color: #07120b;\n    background-color: #42f77b;\n    border-radius: 8px;\n}\n\n.cb-manager-btn {\n    color: #07111a;\n    background-color: #ffd23f;\n    border-color: #ffe98a;\n\n    \u0026:hover {\n        background-color: #ffe06a;\n        border-color: #ffffff;\n    }\n}\n\n.cb-manager-panel {\n    min-width: 620px;\n    max-width: 760px;\n}\n\n.cb-manager-list {\n    display: flex;\n    flex-direction: column;\n    gap: 10px;\n    width: 660px;\n    max-height: 460px;\n    overflow-y: scroll;\n    padding-right: 4px;\n}\n\n.cb-manager-empty {\n    padding: 28px;\n    font-size: 17px;\n    font-weight: 800;\n    text-align: center;\n    color: rgba(255, 255, 255, 0.6);\n}\n\n.cb-report-row {\n    display: flex;\n    flex-direction: column;\n    gap: 6px;\n    padding: 12px 14px;\n    background-color: rgba(255, 255, 255, 0.06);\n    border: 1px solid rgba(255, 255, 255, 0.14);\n    border-left-width: 4px;\n    border-left-color: #ff7a59;\n    border-radius: 8px;\n\n    \u0026.resolved {\n        border-left-color: #42f77b;\n        opacity: 0.7;\n    }\n}\n\n.cb-report-head {\n    display: flex;\n    flex-direction: row;\n    align-items: center;\n    gap: 10px;\n}\n\n.cb-report-when {\n    font-size: 13px;\n    font-weight: 900;\n    color: #aeefff;\n}\n\n.cb-report-meta {\n    flex-grow: 1;\n    font-size: 13px;\n    font-weight: 700;\n    color: rgba(255, 255, 255, 0.66);\n}\n\n.cb-report-tag {\n    padding: 2px 8px;\n    font-size: 12px;\n    font-weight: 900;\n    color: #07120b;\n    background-color: #42f77b;\n    border-radius: 10px;\n}\n\n.cb-report-msg {\n    font-size: 16px;\n    font-weight: 600;\n    line-height: 20px;\n    color: #ffffff;\n    white-space: pre-wrap;\n}\n\n.cb-report-actions {\n    display: flex;\n    flex-direction: row;\n    justify-content: flex-end;\n    gap: 8px;\n    margin-top: 2px;\n}\n\n.cb-mini-btn {\n    pointer-events: all;\n    padding: 6px 14px;\n    font-size: 14px;\n    font-weight: 900;\n    color: #07111a;\n    background-color: #aeefff;\n    border: 1px solid rgba(255, 255, 255, 0.7);\n    border-radius: 6px;\n    cursor: pointer;\n    transition: all 0.10s ease-out;\n\n    \u0026:hover {\n        background-color: #ffffff;\n        transform: scale(1.04);\n    }\n}\n\n.cb-mini-danger {\n    color: #ffffff;\n    background-color: rgba(255, 90, 70, 0.92);\n    border-color: rgba(255, 150, 130, 0.9);\n\n    \u0026:hover {\n        background-color: #ff5a46;\n    }\n}\n"},{"Ident":"verarp.colour_break","Path":"ColourBreakProgressStore.cs","FileName":"ColourBreakProgressStore.cs","PackageType":"game","CodeKind":"Game","AssetVersionId":292528,"IsPrivate":false,"Code":"using Sandbox;\nusing System;\n\npublic static class ColourBreakProgressStore\n{\n\tconst string ProgressCookieKey = \u0022colourbreak.progress.v1\u0022;\n\n\tpublic static ColourBreakSaveData Load()\n\t{\n\t\tColourBreakSaveData data;\n\t\ttry\n\t\t{\n\t\t\tdata = Game.Cookies.Get( ProgressCookieKey, new ColourBreakSaveData() ) ?? new ColourBreakSaveData();\n\t\t}\n\t\tcatch ( Exception e )\n\t\t{\n\t\t\tLog.Warning( $\u0022Could not load Colour Break progress: {e.Message}\u0022 );\n\t\t\tdata = new ColourBreakSaveData();\n\t\t}\n\n\t\tNormalize( data );\n\t\treturn data;\n\t}\n\n\tpublic static void Save( ColourBreakSaveData data )\n\t{\n\t\tNormalize( data );\n\n\t\ttry\n\t\t{\n\t\t\tGame.Cookies.Set( ProgressCookieKey, data );\n\t\t}\n\t\tcatch ( Exception e )\n\t\t{\n\t\t\tLog.Warning( $\u0022Could not save Colour Break progress: {e.Message}\u0022 );\n\t\t}\n\t}\n\n\tpublic static int GetBestStars( ColourBreakSaveData data, int levelIndex )\n\t{\n\t\tif ( data?.BestStars == null )\n\t\t\treturn 0;\n\n\t\tif ( levelIndex \u003C 0 || levelIndex \u003E= data.BestStars.Length )\n\t\t\treturn 0;\n\n\t\treturn Math.Clamp( data.BestStars[levelIndex], 0, 3 );\n\t}\n\n\tpublic static bool RecordEndlessScore( ColourBreakSaveData data, int score )\n\t{\n\t\tNormalize( data );\n\n\t\tif ( score \u003C= data.BestEndlessScore )\n\t\t\treturn false;\n\n\t\tdata.BestEndlessScore = score;\n\t\tSave( data );\n\t\treturn true;\n\t}\n\n\tpublic static void RecordWin( ColourBreakSaveData data, int levelIndex, int stars, bool hasNextLevel )\n\t{\n\t\tNormalize( data );\n\n\t\tif ( levelIndex \u003E= 0 \u0026\u0026 levelIndex \u003C data.BestStars.Length )\n\t\t\tdata.BestStars[levelIndex] = Math.Max( data.BestStars[levelIndex], Math.Clamp( stars, 1, 3 ) );\n\n\t\tif ( hasNextLevel )\n\t\t\tdata.HighestUnlockedLevel = Math.Max( data.HighestUnlockedLevel, levelIndex \u002B 1 );\n\n\t\tSave( data );\n\t}\n\n\tstatic void Normalize( ColourBreakSaveData data )\n\t{\n\t\tif ( data == null )\n\t\t\treturn;\n\n\t\tdata.HighestUnlockedLevel = Math.Clamp( data.HighestUnlockedLevel, 1, ColourBreakLevels.Count );\n\n\t\tif ( data.BestEndlessScore \u003C 0 )\n\t\t\tdata.BestEndlessScore = 0;\n\n\t\tif ( data.BestStars == null || data.BestStars.Length \u003C ColourBreakLevels.Count \u002B 1 )\n\t\t{\n\t\t\tvar old = data.BestStars;\n\t\t\tdata.BestStars = new int[ColourBreakLevels.Count \u002B 1];\n\t\t\tif ( old != null )\n\t\t\t{\n\t\t\t\tint count = Math.Min( old.Length, data.BestStars.Length );\n\t\t\t\tfor ( int i = 0; i \u003C count; i\u002B\u002B )\n\t\t\t\t\tdata.BestStars[i] = Math.Clamp( old[i], 0, 3 );\n\t\t\t}\n\t\t}\n\n\t\tfor ( int i = 0; i \u003C data.BestStars.Length; i\u002B\u002B )\n\t\t\tdata.BestStars[i] = Math.Clamp( data.BestStars[i], 0, 3 );\n\t}\n}\n"},{"Ident":"verarp.colour_break","Path":"styles/base/_splitcontainer.scss","FileName":"_splitcontainer.scss","PackageType":"game","CodeKind":"Game","AssetVersionId":292528,"IsPrivate":false,"Code":"\r\n.splitcontainer\r\n{\r\n\tflex-grow: 1;\r\n\r\n\t\u003E .split-left, \u003E .split-right\r\n\t{\r\n\t\tflex-grow: 1;\r\n\t}\r\n\r\n\t\u003E .split-left\r\n\t{\r\n\t\theight: 100%;\r\n\t}\r\n\r\n\t\u003E .splitter\r\n\t{\r\n\t\tflex-grow: 1;\r\n\t\twidth: 8px;\r\n\t\tcursor: ew-resize;\r\n\r\n\t\t\u0026:hover\r\n\t\t{\r\n\t\t}\r\n\t}\r\n\r\n\t\u0026.dragging \u003E .splitter\r\n\t{\r\n\t}\r\n\r\n\t\u0026.vertical\r\n\t{\r\n\t\tflex-direction: column;\r\n\r\n\t\t\u003E .splitter\r\n\t\t{\r\n\t\t\theight: 8px;\r\n\t\t\twidth: 100%;\r\n\t\t\tcursor: ns-resize;\r\n\t\t}\r\n\t}\r\n}"},{"Ident":"verarp.colour_break","Path":"styles/base/_navigator.scss","FileName":"_navigator.scss","PackageType":"game","CodeKind":"Game","AssetVersionId":292528,"IsPrivate":false,"Code":".navigator-body\r\n{\r\n\t\u0026.hidden\r\n\t{\r\n\t\tdisplay: none;\r\n\t}\r\n}\r\n"},{"Ident":"verarp.colour_break","Path":"styles/form.scss","FileName":"form.scss","PackageType":"game","CodeKind":"Game","AssetVersionId":292528,"IsPrivate":false,"Code":"\r\n$form-control-height: 28px !default;\r\n\r\n@import \u0022form/_checkbox.scss\u0022;\r\n@import \u0022form/_switch.scss\u0022;\r\n@import \u0022form/_dropdown.scss\u0022;\r\n@import \u0022form/_coloreditor.scss\u0022;\r\n@import \u0022form/_colorproperty.scss\u0022;\r\n\r\n.form\r\n{\r\n\tflex-direction: column;\r\n\talign-items: stretch;\r\n\tjustify-content: flex-start;\r\n\toverflow: scroll;\r\n}\r\n\r\n.field-group\r\n{\r\n\tflex-direction: column;\r\n\tflex-shrink: 0;\r\n}\r\n\r\n.field-header\r\n{\r\n\tflex-shrink: 0;\r\n}\r\n\r\n.field\r\n{\r\n\tcolor: white;\r\n\tfont-size: 14px;\r\n\tflex-shrink: 0;\r\n\tflex-grow: 0;\r\n\r\n\t\u003E .label\r\n\t{\r\n\t\tflex-grow: 0;\r\n\t\tflex-shrink: 0;\r\n\t\tfont-weight: 600;\r\n\t\topacity: 0.4;\r\n\t\twidth: 20%;\r\n\t\tfont-size: 13px;\r\n\t}\r\n\r\n\t\u003E .control\r\n\t{\r\n\t\tflex-shrink: 0;\r\n\t\tflex-grow: 1;\r\n\t\tflex-direction: column;\r\n\t}\r\n}\r\n\r\n.is-vertical \u003E .field, .field.is-vertical\r\n{\r\n\tflex-direction: column;\r\n\r\n\t\u003E .label\r\n\t{\r\n\t\twidth: auto;\r\n\t\theight: auto;\r\n\t}\r\n}"},{"Ident":"verarp.colour_break","Path":"styles/base.scss","FileName":"base.scss","PackageType":"game","CodeKind":"Game","AssetVersionId":292528,"IsPrivate":false,"Code":"@import \u0022base/_splitcontainer.scss\u0022;\r\n@import \u0022base/_navigator.scss\u0022;\r\n\r\nbutton\r\n{\r\n\tcursor: pointer;\r\n}\r\n\r\nIconPanel\r\n{\r\n\tfont-family: Material Icons;\r\n}\r\n\r\n.is-half\r\n{\r\n\twidth: 50%;\r\n}\r\n\r\n.is-third\r\n{\r\n\twidth: 33%;\r\n}\r\n\r\n.is-quarter\r\n{\r\n\twidth: 25%;\r\n}\r\n\r\nbutton.has-subtitle\r\n{\r\n\tposition: relative;\r\n\tflex-direction: column;\r\n\tjustify-content: flex-start;\r\n\talign-items: flex-start;\r\n\tpadding-left: 40px; // icon space\r\n\r\n\t.iconpanel\r\n\t{\r\n\t\tposition: absolute;\r\n\t\tleft: 5px;\r\n\t\ttop: 0;\r\n\t\tbottom: 0;\r\n\t\talign-items: center;\r\n\t}\r\n\r\n\t.button-label\r\n\t{\r\n\t\tfont-weight: bold;\r\n\t}\r\n\r\n\t.button-subtitle\r\n\t{\r\n\t\tfont-size: 12px;\r\n\t\topacity: 0.5;\r\n\t\tmix-blend-mode: lighten;\r\n\t}\r\n}"},{"Ident":"verarp.colour_break","Path":"ui/controls/enumcontrol.cs.scss","FileName":"enumcontrol.cs.scss","PackageType":"game","CodeKind":"Game","AssetVersionId":292528,"IsPrivate":false,"Code":"EnumControl\r\n{\r\n\tgap: 2px;\r\n\tflex-grow: 1;\r\n}\r\n\r\nEnumControl DropDown,\r\nEnumControl ButtonGroup\r\n{\r\n\tborder-radius: 8px;\r\n\tbackground-color: #000a;\r\n\tflex-grow: 1;\r\n}\r\n\r\nEnumControl DropDown\r\n{\r\n\tflex-grow: 1;\r\n\tmin-height: 32px;\r\n}\r\n\r\nEnumControl ButtonGroup\r\n{\r\n\tborder-radius: 12px;\r\n\toverflow: hidden;\r\n\tmin-height: 32px;\r\n\r\n\tButton\r\n\t{\r\n\t\tflex-grow: 1;\r\n\t\tjustify-content: center;\r\n\t\talign-items: center;\r\n\t\tgap: 4px;\r\n\t\tcolor: #aaa;\r\n\t\tfont-size: 1rem;\r\n\t\tcursor: pointer;\r\n\r\n\t\t.icon\r\n\t\t{\r\n\t\t\tcolor: #08f;\r\n\t\t}\r\n\r\n\t\t\u0026:hover\r\n\t\t{\r\n\t\t\tcolor: #ddd;\r\n\r\n\t\t\t.icon\r\n\t\t\t{\r\n\t\t\t\tcolor: #3af;\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\t\u0026:active\r\n\t\t{\r\n\t\t\tbackground-color: #04a;\r\n\t\t\tcolor: white;\r\n\t\t\ttransform: translateX( 1px ) translateY( 1px );\r\n\r\n\t\t\t.icon\r\n\t\t\t{\r\n\t\t\t\tcolor: #fff;\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\t\u0026.active\r\n\t\t{\r\n\t\t\tbackground-color: #08f;\r\n\t\t\tcolor: white;\r\n\t\t\tpointer-events: none;\r\n\r\n\t\t\t.icon\r\n\t\t\t{\r\n\t\t\t\tcolor: #fff;\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n}"},{"Ident":"verarp.colour_break","Path":"ColourBreakSaveData.cs","FileName":"ColourBreakSaveData.cs","PackageType":"game","CodeKind":"Game","AssetVersionId":292528,"IsPrivate":false,"Code":"public sealed class ColourBreakSaveData\n{\n\tpublic int HighestUnlockedLevel { get; set; } = 1;\n\tpublic int[] BestStars { get; set; } = new int[ColourBreakLevels.Count \u002B 1];\n\tpublic int BestEndlessScore { get; set; }\n}\n"},{"Ident":"verarp.colour_break","Path":"ui/components/packageflairbar.razor.scss","FileName":"packageflairbar.razor.scss","PackageType":"game","CodeKind":"Game","AssetVersionId":292528,"IsPrivate":false,"Code":"PackageFlairBar\r\n{\r\n\tposition: absolute;\r\n\ttop: 6px;\r\n\tleft: 6px;\r\n\tz-index: 2;\r\n\tflex-direction: row;\r\n\tgap: 5px;\r\n\tpointer-events: none;\r\n\r\n\t.flair\r\n\t{\r\n\t\tposition: relative;\r\n\t\talign-items: center;\r\n\t\tjustify-content: center;\r\n\t\twidth: 22px;\r\n\t\theight: 22px;\r\n\t\tpointer-events: all;\r\n\t\tborder-radius: 4px;\r\n\t\tcolor: white;\r\n\t\tborder: 1px solid rgba( white, 0.1 );\r\n\t\toutline: 1px solid #0006;\r\n\t\topacity: 0.7;\r\n\r\n\t\t\u0026:hover\r\n\t\t{\r\n\t\t\topacity: 1;\r\n\t\t}\r\n\r\n\t\ticon\r\n\t\t{\r\n\t\t\tfont-size: 15px;\r\n\t\t}\r\n\t}\r\n}\r\n"},{"Ident":"verarp.colour_break","Path":"ColourBreakBugReportStore.cs","FileName":"ColourBreakBugReportStore.cs","PackageType":"game","CodeKind":"Game","AssetVersionId":292528,"IsPrivate":false,"Code":"using Sandbox;\nusing System;\nusing System.Linq;\nusing System.Collections.Generic;\n\n// Local persistence for bug reports, stored in a cookie like the progress store.\n// No network calls \u2014 the dev reads them in-game via the hidden manager.\npublic static class ColourBreakBugReportStore\n{\n\tconst string CookieKey = \u0022colourbreak.bugreports.v1\u0022;\n\tconst int MaxReports = 200;\n\tconst int MaxMessageLength = 600;\n\n\tpublic static ColourBreakBugReportLog Load()\n\t{\n\t\ttry\n\t\t{\n\t\t\treturn Game.Cookies.Get( CookieKey, new ColourBreakBugReportLog() ) ?? new ColourBreakBugReportLog();\n\t\t}\n\t\tcatch ( Exception e )\n\t\t{\n\t\t\tLog.Warning( $\u0022Could not load bug reports: {e.Message}\u0022 );\n\t\t\treturn new ColourBreakBugReportLog();\n\t\t}\n\t}\n\n\tpublic static void Save( ColourBreakBugReportLog log )\n\t{\n\t\tif ( log == null ) return;\n\t\ttry\n\t\t{\n\t\t\tGame.Cookies.Set( CookieKey, log );\n\t\t}\n\t\tcatch ( Exception e )\n\t\t{\n\t\t\tLog.Warning( $\u0022Could not save bug reports: {e.Message}\u0022 );\n\t\t}\n\t}\n\n\tpublic static List\u003CColourBreakBugReport\u003E GetAll()\n\t{\n\t\treturn Load().Reports ?? new List\u003CColourBreakBugReport\u003E();\n\t}\n\n\tpublic static int OpenCount()\n\t{\n\t\treturn GetAll().Count( r =\u003E r != null \u0026\u0026 !r.Resolved );\n\t}\n\n\tpublic static bool Add( ColourBreakBugReport report )\n\t{\n\t\tif ( report == null )\n\t\t\treturn false;\n\n\t\treport.Message = (report.Message ?? \u0022\u0022).Trim();\n\t\tif ( string.IsNullOrWhiteSpace( report.Message ) )\n\t\t\treturn false;\n\n\t\tif ( report.Message.Length \u003E MaxMessageLength )\n\t\t\treport.Message = report.Message.Substring( 0, MaxMessageLength );\n\n\t\tvar log = Load();\n\t\tlog.Reports ??= new List\u003CColourBreakBugReport\u003E();\n\t\tlog.Reports.Insert( 0, report );   // newest first\n\t\tif ( log.Reports.Count \u003E MaxReports )\n\t\t\tlog.Reports.RemoveRange( MaxReports, log.Reports.Count - MaxReports );\n\n\t\tSave( log );\n\t\treturn true;\n\t}\n\n\tpublic static void SetResolved( string id, bool resolved )\n\t{\n\t\tvar log = Load();\n\t\tvar r = log.Reports?.FirstOrDefault( x =\u003E x != null \u0026\u0026 x.Id == id );\n\t\tif ( r == null ) return;\n\t\tr.Resolved = resolved;\n\t\tSave( log );\n\t}\n\n\tpublic static void Delete( string id )\n\t{\n\t\tvar log = Load();\n\t\tlog.Reports?.RemoveAll( x =\u003E x == null || x.Id == id );\n\t\tSave( log );\n\t}\n\n\tpublic static void Clear()\n\t{\n\t\tSave( new ColourBreakBugReportLog() );\n\t}\n}\n"},{"Ident":"verarp.colour_break","Path":"ColourBreakGame.cs","FileName":"ColourBreakGame.cs","PackageType":"game","CodeKind":"Game","AssetVersionId":292528,"IsPrivate":false,"Code":"using Sandbox;\nusing System;\nusing System.Collections.Generic;\n\npublic sealed class ColourBreakGame : Component\n{\n\tconst int Empty = -1;\n\n\t[Property] public int Width { get; set; } = 8;\n\t[Property] public int Height { get; set; } = 8;\n\t[Property] public float CellSpacing { get; set; } = 48f;\n\t[Property] public float CandyScale { get; set; } = 0.50f;\n\t[Property] public Vector3 BoardOrigin { get; set; } = Vector3.Zero;\n\t[Property] public Model CandyModel { get; set; }\n\t[Property] public int CandyTypeCount { get; set; } = 6;\n\t[Property] public bool AutoFrameMainCamera { get; set; } = true;\n\t[Property] public int LevelIndex { get; set; } = 1;\n\t[Property] public int TargetScore { get; set; } = 850;\n\t[Property] public int MoveLimit { get; set; } = 24;\n\t[Property] public bool AudioEnabled { get; set; } = true;\n\t[Property] public bool EffectsEnabled { get; set; } = true;\n\t[Property] public bool CameraShakeEnabled { get; set; } = true;\n\t[Property] public bool ColourBlindMode { get; set; }\n\t[Property] public string StartSound { get; set; } = \u0022sounds/colourbreak_start.sound\u0022;\n\t[Property] public string SwapSound { get; set; } = \u0022sounds/colourbreak_swap.sound\u0022;\n\t[Property] public string ClearSound { get; set; } = \u0022sounds/colourbreak_clear.sound\u0022;\n\t[Property] public string ComboSound { get; set; } = \u0022sounds/colourbreak_combo.sound\u0022;\n\t[Property] public string DeniedSound { get; set; } = \u0022sounds/colourbreak_denied.sound\u0022;\n\t[Property] public bool MusicEnabled { get; set; } = true;\n\t[Property] public string MusicSound { get; set; } = \u0022sounds/colourbreak_music.sound\u0022;\n\t[Property, Range( 0f, 1f )] public float MusicVolume { get; set; } = 0.42f;\n\t[Property] public GameMode Mode { get; set; } = GameMode.Levels;\n\n\t// Endless uses the full palette and the largest shape set available.\n\tconst int EndlessColourCount = 6;\n\n\tModel _sphereModel;\n\tModel _boxModel;\n\n\tModel ModelForType( int t ) =\u003E _sphereModel ?? _boxModel;\n\tColor PieceColor( int type ) =\u003E (ColourBlindMode ? ColourBlindPalette : Palette)[Math.Clamp( type, 0, Palette.Length - 1 )];\n\tVector3 PieceShape( int type ) =\u003E (ColourBlindMode ? ColourBlindShapes : Shapes)[Math.Clamp( type, 0, Shapes.Length - 1 )];\n\n\t// Distinct saturated colours that read quickly under motion and bloom.\n\treadonly Color[] Palette = new[]\n\t{\n\t\tnew Color( 1.00f, 0.05f, 0.15f ), // bright red\n\t\tnew Color( 1.00f, 0.50f, 0.00f ), // bright orange\n\t\tnew Color( 1.00f, 0.95f, 0.00f ), // bright yellow\n\t\tnew Color( 0.15f, 0.90f, 0.15f ), // bright green\n\t\tnew Color( 0.05f, 0.55f, 1.00f ), // bright blue\n\t\tnew Color( 0.80f, 0.15f, 1.00f ), // bright purple\n\t};\n\n\t// Okabe-Ito-derived hues, pushed brighter/more saturated so they stay distinct\n\t// under bloom. Backed up by the per-type shape symbols in ApplyColourBlindSymbol.\n\treadonly Color[] ColourBlindPalette = new[]\n\t{\n\t\tnew Color( 1.00f, 0.55f, 0.00f ), // vivid orange\n\t\tnew Color( 0.30f, 0.78f, 1.00f ), // sky blue\n\t\tnew Color( 0.00f, 0.78f, 0.50f ), // bluish green\n\t\tnew Color( 1.00f, 0.95f, 0.20f ), // yellow\n\t\tnew Color( 0.05f, 0.35f, 0.95f ), // deep blue\n\t\tnew Color( 0.95f, 0.40f, 0.70f ), // reddish purple / pink\n\t};\n\n\treadonly string[] ColourNames =\n\t{\n\t\t\u0022Ruby\u0022,\n\t\t\u0022Amber\u0022,\n\t\t\u0022Gold\u0022,\n\t\t\u0022Lime\u0022,\n\t\t\u0022Azure\u0022,\n\t\t\u0022Violet\u0022,\n\t};\n\n\treadonly Vector3[] Shapes = new[]\n\t{\n\t\tnew Vector3( 1.00f, 1.00f, 1.00f ),\n\t\tnew Vector3( 1.18f, 0.92f, 1.08f ),\n\t\tnew Vector3( 0.92f, 1.08f, 1.24f ),\n\t\tnew Vector3( 1.08f, 1.00f, 0.86f ),\n\t\tnew Vector3( 0.94f, 1.06f, 1.14f ),\n\t\tnew Vector3( 1.10f, 0.90f, 0.98f ),\n\t\tnew Vector3( 1.00f, 1.00f, 1.00f ),\n\t};\n\n\treadonly Vector3[] ColourBlindShapes = new[]\n\t{\n\t\tnew Vector3( 0.78f, 1.00f, 1.42f ),\n\t\tnew Vector3( 1.42f, 0.92f, 0.78f ),\n\t\tnew Vector3( 1.00f, 1.00f, 1.00f ),\n\t\tnew Vector3( 1.28f, 0.92f, 1.28f ),\n\t\tnew Vector3( 0.78f, 1.08f, 0.78f ),\n\t\tnew Vector3( 1.48f, 0.86f, 1.08f ),\n\t\tnew Vector3( 1.00f, 1.00f, 1.00f ),\n\t};\n\n\treadonly Dictionary\u003Cstring, bool\u003E _prevKeys = new();\n\n\tint[,] _types;\n\tSpecialKind[,] _specials;\n\tCandyVisual[,] _visuals;\n\treadonly List\u003CGameObject\u003E _decor = new();\n\n\tint _cursorX;\n\tint _cursorY;\n\tbool _hasSelection;\n\tint _selectedX;\n\tint _selectedY;\n\n\tint _score;\n\tint _moves;\n\tint _objectiveProgress;\n\tColourBreakSaveData _saveData = new();\n\tbool _prevMouseLeft;\n\tfloat _controllerMoveCooldown;\n\n\tbool _dragging;\n\tint _dragStartX;\n\tint _dragStartY;\n\tbool _dragSwapped;\n\n\t// Idle hint: after a stretch of inactivity, gently pulse a valid move so the\n\t// player is never truly stuck staring at the board.\n\tfloat _idleTime;\n\tbool _hasHint;\n\tint _hintAX, _hintAY, _hintBX, _hintBY;\n\tconst float HintDelay = 5.0f;\n\n\t// Tracks whether the player has ever made a swap this session, so the\n\t// how-to-play prompt can fade out once they clearly understand the controls.\n\tbool _hasEverSwapped;\n\n\t// High-level game state driving the menus\n\tpublic enum GameState { Menu, Playing, Paused, Won, Lost }\n\tpublic enum GameMode { Levels, Endless }\n\tpublic GameState CurrentState { get; private set; } = GameState.Menu;\n\tpublic bool IsEndless =\u003E Mode == GameMode.Endless;\n\tenum SpecialKind { None, RowBlast, ColumnBlast, Bomb }\n\n\t// Exposed for the UI / HUD\n\tpublic int Score =\u003E _score;\n\tpublic int Moves =\u003E _moves;\n\tpublic int MovesLeft =\u003E Math.Max( 0, MoveLimit - _moves );\n\tpublic int GoalScore =\u003E TargetScore;\n\tpublic int Level =\u003E LevelIndex;\n\tpublic int ColourCount =\u003E CandyTypeCount;\n\tColourBreakLevelDefinition CurrentLevelDefinition =\u003E ColourBreakLevels.Get( LevelIndex );\n\tpublic string LevelName =\u003E CurrentLevelDefinition.Name;\n\tpublic string LevelBrief =\u003E CurrentLevelDefinition.Brief;\n\tpublic int LevelCount =\u003E ColourBreakLevels.Count;\n\tpublic bool HasNextLevel =\u003E LevelIndex \u003C ColourBreakLevels.Count;\n\tpublic int HighestUnlockedLevel =\u003E Math.Clamp( _saveData?.HighestUnlockedLevel ?? 1, 1, LevelCount );\n\tpublic int BestStars =\u003E ColourBreakProgressStore.GetBestStars( _saveData, LevelIndex );\n\tpublic int TotalStars\n\t{\n\t\tget\n\t\t{\n\t\t\tint total = 0;\n\t\t\tfor ( int i = 1; i \u003C= LevelCount; i\u002B\u002B )\n\t\t\t\ttotal \u002B= ColourBreakProgressStore.GetBestStars( _saveData, i );\n\t\t\treturn total;\n\t\t}\n\t}\n\tpublic int MaxStars =\u003E LevelCount * 3;\n\tpublic int EndlessBest =\u003E Math.Max( 0, _saveData?.BestEndlessScore ?? 0 );\n\tpublic bool EndlessRecordSet { get; private set; }\n\tpublic bool SelectedLevelLocked =\u003E LevelIndex \u003E HighestUnlockedLevel;\n\tpublic bool CanPlaySelectedLevel =\u003E !SelectedLevelLocked;\n\tpublic bool CanSelectPreviousLevel =\u003E CurrentState == GameState.Menu \u0026\u0026 LevelIndex \u003E 1;\n\tpublic bool CanSelectNextLevel =\u003E CurrentState == GameState.Menu \u0026\u0026 LevelIndex \u003C LevelCount;\n\tpublic bool HasSecondaryObjective =\u003E CurrentLevelDefinition.ObjectiveKind != ColourBreakObjectiveKind.Score \u0026\u0026 CurrentLevelDefinition.ObjectiveTarget \u003E 0;\n\tpublic int ObjectiveProgress =\u003E HasSecondaryObjective ? Math.Min( _objectiveProgress, CurrentLevelDefinition.ObjectiveTarget ) : 0;\n\tpublic int ObjectiveTarget =\u003E HasSecondaryObjective ? CurrentLevelDefinition.ObjectiveTarget : 0;\n\tpublic string ObjectiveText =\u003E ObjectiveLabel();\n\tpublic string ObjectiveProgressText =\u003E HasSecondaryObjective\n\t\t? $\u0022{ObjectiveProgress} / {ObjectiveTarget}\u0022\n\t\t: \u0022Score target\u0022;\n\tpublic bool ObjectiveComplete =\u003E !HasSecondaryObjective || _objectiveProgress \u003E= CurrentLevelDefinition.ObjectiveTarget;\n\tpublic int CompletionStars\n\t{\n\t\tget\n\t\t{\n\t\t\tif ( CurrentState != GameState.Won )\n\t\t\t\treturn 0;\n\n\t\t\tint stars = 1;\n\t\t\tif ( MovesLeft \u003E= Math.Max( 3, MoveLimit / 4 ) )\n\t\t\t\tstars\u002B\u002B;\n\t\t\tif ( _score \u003E= MathF.Ceiling( TargetScore * 1.25f ) )\n\t\t\t\tstars\u002B\u002B;\n\n\t\t\treturn Math.Clamp( stars, 1, 3 );\n\t\t}\n\t}\n\tpublic string CompletionRank =\u003E CompletionStars switch\n\t{\n\t\t3 =\u003E \u0022Perfect Break\u0022,\n\t\t2 =\u003E \u0022Clean Break\u0022,\n\t\t1 =\u003E \u0022Level Clear\u0022,\n\t\t_ =\u003E \u0022Keep Going\u0022\n\t};\n\tpublic int ComboCount =\u003E _comboCount;\n\tpublic bool HasLegalMove =\u003E HasPossibleMove();\n\tpublic bool MusicIsPlaying =\u003E _music.IsValid() \u0026\u0026 _music.IsPlaying;\n\tpublic int ActiveSpecialCount =\u003E CountSpecials();\n\t// Drives the one-time how-to-play prompt and the \u0022stuck?\u0022 hint banner in the HUD.\n\tpublic bool ShowHowToPlay =\u003E CurrentState == GameState.Playing \u0026\u0026 !_hasEverSwapped;\n\tpublic bool HintActive =\u003E _hasHint \u0026\u0026 CurrentState == GameState.Playing;\n\tpublic string StatusText =\u003E _phase switch\n\t{\n\t\tPhase.SwapForward =\u003E \u0022Swapping\u0022,\n\t\tPhase.SwapBack =\u003E \u0022Try another move\u0022,\n\t\tPhase.Clearing =\u003E _comboCount \u003E 1 ? $\u0022Combo x{_comboCount}\u0022 : \u0022Colour break\u0022,\n\t\tPhase.Collapsing =\u003E \u0022Dropping\u0022,\n\t\tPhase.Refilling =\u003E \u0022Refilling\u0022,\n\t\tPhase.Pause =\u003E _comboCount \u003E 1 ? $\u0022Chain x{_comboCount}\u0022 : \u0022Scoring\u0022,\n\t\t_ when _hasSelection =\u003E \u0022Pick a neighbour\u0022,\n\t\t_ =\u003E CurrentState switch\n\t\t{\n\t\t\tGameState.Won =\u003E \u0022Level complete\u0022,\n\t\t\tGameState.Lost =\u003E IsEndless ? \u0022No moves left\u0022 : \u0022Out of moves\u0022,\n\t\t\tGameState.Playing =\u003E IsEndless ? \u0022Keep the chain alive\u0022 : \u0022Find a colour chain\u0022,\n\t\t\t_ =\u003E \u0022Ready\u0022\n\t\t}\n\t};\n\n\t// Resolve / animation state machine\n\tenum Phase { Idle, SwapForward, ValidateAndClear, Clearing, Collapsing, Refilling, Pause, SwapBack }\n\tPhase _phase = Phase.Idle;\n\tfloat _phaseTimer;\n\tint _swapAX, _swapAY, _swapBX, _swapBY;\n\tint _comboCount;\n\n\t// Camera punch\n\tCameraComponent _activeCamera;\n\tfloat _baseFov = 60f;\n\tfloat _fovPunch;\n\tfloat _shakeAmount;\n\tVector3 _baseCameraPos;\n\n\t// Orbiting accent lights\n\tGameObject _orbitLightL;\n\tGameObject _orbitLightR;\n\n\t// Color-shifting tray\n\tModelRenderer _trayInnerRenderer;\n\tColor _trayBaseColor = new Color( 0.62f, 0.70f, 0.92f );\n\n\tconst float SwapDuration = 0.18f;\n\tconst float ClearDuration = 0.28f;\n\tconst float FallSpeed = 1100f; // units per second\n\tconst float CascadePause = 0.05f;\n\n\tsealed class CandyVisual\n\t{\n\t\tpublic GameObject Go;\n\t\tpublic ModelRenderer Renderer;\n\t\tpublic GameObject Shine;\n\t\tpublic ModelRenderer ShineRenderer;\n\t\tpublic GameObject Rim;\n\t\tpublic ModelRenderer RimRenderer;\n\t\tpublic GameObject Accent;\n\t\tpublic ModelRenderer AccentRenderer;\n\t\tpublic GameObject SymbolA;\n\t\tpublic ModelRenderer SymbolARenderer;\n\t\tpublic GameObject SymbolB;\n\t\tpublic ModelRenderer SymbolBRenderer;\n\t\tpublic GameObject Face;\n\t\tpublic ModelRenderer FaceRenderer;\n\t\tpublic GameObject Halo;\n\t\tpublic ModelRenderer HaloRenderer;\n\t\tpublic GameObject Guide;\n\t\tpublic ModelRenderer GuideRenderer;\n\t\tpublic GameObject SpecialBadge;\n\t\tpublic ModelRenderer SpecialBadgeRenderer;\n\t\tpublic int Type;\n\t\tpublic SpecialKind Special;\n\t\tpublic Vector3 Anchor;          // resting/target world position\n\t\tpublic Vector3 Velocity;        // for falling\n\t\tpublic float BobPhase;\n\t\tpublic float ClearTimer;        // \u003E 0 while playing destroy anim\n\t\tpublic bool Clearing;\n\t\tpublic bool Spawning;           // newly spawned, scaling up from 0\n\t\tpublic float SpawnTimer;\n\t\tpublic float SwapT;             // 0..1 progress for swap tween\n\t\tpublic Vector3 SwapFrom;\n\t\tpublic Vector3 SwapTo;\n\t\tpublic bool Swapping;\n\t}\n\n\tsealed class Burst\n\t{\n\t\tpublic GameObject Go;\n\t\tpublic ModelRenderer Renderer;\n\t\tpublic Vector3 Velocity;\n\t\tpublic float Life;\n\t\tpublic float MaxLife;\n\t\tpublic Color BaseTint;\n\t\tpublic float StartScale;\n\t}\n\n\treadonly List\u003CBurst\u003E _bursts = new();\n\n\t// Particle pool. Bursts/fire spawn dozens of short-lived renderer objects per\n\t// clear; recycling them instead of new/Destroy each time avoids GC churn.\n\treadonly Stack\u003CGameObject\u003E _burstPool = new();\n\tconst int MaxPooledBursts = 256;\n\n\tGameObject RentBurstObject( string name )\n\t{\n\t\tGameObject go;\n\t\tif ( _burstPool.Count \u003E 0 )\n\t\t{\n\t\t\tgo = _burstPool.Pop();\n\t\t\tgo.Name = name;\n\t\t\tgo.Enabled = true;\n\t\t}\n\t\telse\n\t\t{\n\t\t\tgo = new GameObject( true, name );\n\t\t\tgo.Flags = GameObjectFlags.NotNetworked;\n\t\t\tgo.AddComponent\u003CModelRenderer\u003E();\n\t\t}\n\t\treturn go;\n\t}\n\n\tvoid ReturnBurstObject( GameObject go )\n\t{\n\t\tif ( go == null || !go.IsValid() ) return;\n\t\tif ( _burstPool.Count \u003E= MaxPooledBursts )\n\t\t{\n\t\t\tgo.Destroy();\n\t\t\treturn;\n\t\t}\n\t\tgo.Enabled = false;\n\t\tgo.SetParent( null );\n\t\t_burstPool.Push( go );\n\t}\n\n\tsealed class Shockwave\n\t{\n\t\tpublic GameObject Go;\n\t\tpublic ModelRenderer Renderer;\n\t\tpublic Color Tint;\n\t\tpublic float Life;\n\t\tpublic float MaxLife;\n\t\tpublic float Radius;\n\t}\n\n\treadonly List\u003CShockwave\u003E _shockwaves = new();\n\n\tfloat _audioCooldown;\n\tSoundHandle _music;\n\n\t// -------------------- lifecycle --------------------\n\n\tprotected override void OnStart()\n\t{\n\t\tbase.OnStart();\n\n\t\t_saveData = ColourBreakProgressStore.Load();\n\t\tApplyLevelSettings();\n\t\t_boxModel = Model.Load( \u0022models/dev/box.vmdl\u0022 );\n\t\t_sphereModel = Model.Load( \u0022models/dev/sphere.vmdl\u0022 );\n\t\tCandyModel ??= _boxModel;\n\n\t\tEnsureSceneLighting();\n\t\tBuildEnvironment();\n\t\tBuildFreshBoard();\n\n\t\tif ( AutoFrameMainCamera )\n\t\t\tFrameMainCameraToBoard();\n\n\t\tMouse.Visibility = MouseVisibility.Visible;\n\n\t\t// Start at the main menu; the board sits in the background as a live backdrop.\n\t\tCurrentState = GameState.Menu;\n\n\t\tLog.Info( \u0022Colour Break ready. Press Play to start. Drag a colour piece onto an adjacent one to swap. R resets, Esc pauses.\u0022 );\n\t}\n\n\tprotected override void OnUpdate()\n\t{\n\t\tHandlePauseHotkeys();\n\t\tUpdateMusic();\n\n\t\t// Paused: freeze the board entirely until the player resumes.\n\t\tif ( CurrentState == GameState.Paused )\n\t\t\treturn;\n\n\t\tAnimateCandies();\n\t\tAnimateBursts();\n\t\tAnimateShockwaves();\n\t\tUpdatePhase();\n\t\tUpdateAmbience();\n\t\tUpdateCameraPunch();\n\t\t_audioCooldown = MathF.Max( 0f, _audioCooldown - Time.Delta );\n\t\t_controllerMoveCooldown = MathF.Max( 0f, _controllerMoveCooldown - Time.Delta );\n\n\t\t// Only accept gameplay input while actually playing.\n\t\tif ( CurrentState == GameState.Playing \u0026\u0026 _phase == Phase.Idle )\n\t\t{\n\t\t\tHandleMouse();\n\t\t\tHandleInput();\n\t\t}\n\n\t\tUpdateHint();\n\t\tApplyHighlights();\n\t}\n\n\t// -------------------- game state / menu API --------------------\n\n\tvoid ApplyLevelSettings()\n\t{\n\t\tLevelIndex = Math.Clamp( LevelIndex, 1, ColourBreakLevels.Count );\n\n\t\tvar level = CurrentLevelDefinition;\n\t\tTargetScore = level.TargetScore;\n\t\tMoveLimit = level.MoveLimit;\n\t\tCandyTypeCount = Math.Clamp( level.ColourCount, 4, Math.Min( Palette.Length, Shapes.Length ) );\n\t}\n\n\tpublic int GetBestStars( int levelIndex )\n\t{\n\t\treturn ColourBreakProgressStore.GetBestStars( _saveData, levelIndex );\n\t}\n\n\tvoid SaveWinProgress()\n\t{\n\t\tColourBreakProgressStore.RecordWin( _saveData, LevelIndex, CompletionStars, HasNextLevel );\n\t\tSubmitLeaderboardStats();\n\t}\n\n\t// Cumulative stats feed s\u0026box leaderboards once the published package defines\n\t// them. Guarded so it is a harmless no-op in the editor / offline.\n\tvoid SubmitLeaderboardStats()\n\t{\n\t\ttry\n\t\t{\n\t\t\tSandbox.Services.Stats.Increment( \u0022levels-cleared\u0022, 1 );\n\t\t\tSandbox.Services.Stats.Increment( \u0022stars-earned\u0022, CompletionStars );\n\t\t\tSandbox.Services.Stats.Increment( \u0022total-score\u0022, _score );\n\t\t}\n\t\tcatch ( Exception e )\n\t\t{\n\t\t\tLog.Info( $\u0022Leaderboard stats unavailable: {e.Message}\u0022 );\n\t\t}\n\t}\n\n\tstring ObjectiveLabel()\n\t{\n\t\tvar level = CurrentLevelDefinition;\n\t\treturn level.ObjectiveKind switch\n\t\t{\n\t\t\tColourBreakObjectiveKind.ClearPieces =\u003E $\u0022Break {level.ObjectiveTarget} pieces\u0022,\n\t\t\tColourBreakObjectiveKind.ClearColour =\u003E $\u0022Break {level.ObjectiveTarget} {ColourName( level.ObjectiveType )}\u0022,\n\t\t\tColourBreakObjectiveKind.MakeSpecials =\u003E $\u0022Create {level.ObjectiveTarget} specials\u0022,\n\t\t\tColourBreakObjectiveKind.TriggerSpecials =\u003E $\u0022Trigger {level.ObjectiveTarget} specials\u0022,\n\t\t\tColourBreakObjectiveKind.ChainCombos =\u003E $\u0022Chain {level.ObjectiveTarget} cascades\u0022,\n\t\t\t_ =\u003E $\u0022Score {TargetScore}\u0022\n\t\t};\n\t}\n\n\tstring ColourName( int type )\n\t{\n\t\tif ( type \u003E= 0 \u0026\u0026 type \u003C ColourNames.Length )\n\t\t\treturn ColourNames[type];\n\n\t\treturn \u0022colour\u0022;\n\t}\n\n\tvoid ApplyEndlessSettings()\n\t{\n\t\tCandyTypeCount = Math.Clamp( EndlessColourCount, 4, Math.Min( Palette.Length, Shapes.Length ) );\n\t\tTargetScore = int.MaxValue;   // no score win condition in endless\n\t\tMoveLimit = int.MaxValue;     // no move limit in endless\n\t}\n\n\t// Switch the selected mode from the main menu and refresh the backdrop board.\n\tpublic void SetMode( GameMode mode )\n\t{\n\t\tif ( CurrentState != GameState.Menu || Mode == mode )\n\t\t\treturn;\n\n\t\tMode = mode;\n\t\tif ( IsEndless ) ApplyEndlessSettings();\n\t\telse ApplyLevelSettings();\n\t\tBuildFreshBoard();\n\t}\n\n\tpublic void SelectLevelsMode() =\u003E SetMode( GameMode.Levels );\n\tpublic void SelectEndlessMode() =\u003E SetMode( GameMode.Endless );\n\n\tpublic void StartNewGame()\n\t{\n\t\tEndlessRecordSet = false;\n\n\t\tif ( IsEndless )\n\t\t{\n\t\t\tApplyEndlessSettings();\n\t\t}\n\t\telse\n\t\t{\n\t\t\tApplyLevelSettings();\n\t\t\tif ( SelectedLevelLocked )\n\t\t\t{\n\t\t\t\tLevelIndex = HighestUnlockedLevel;\n\t\t\t\tApplyLevelSettings();\n\t\t\t}\n\t\t}\n\n\t\tBuildFreshBoard();\n\t\tCurrentState = GameState.Playing;\n\t\t_comboCount = 0;\n\t\tPlayUiSound( StartSound, 0.85f, 1f );\n\t\tSpawnFireColumn( BoardOrigin \u002B new Vector3( 0f, -14f, 0f ), 0.80f );\n\t\tSpawnShockwave( BoardOrigin, new Color( 1f, 0.42f, 0.08f ), 0.55f, 110f );\n\t\tPunchCamera( 3.5f, 2.0f );\n\t\tMouse.Visibility = MouseVisibility.Visible;\n\t}\n\n\tpublic void RestartGame() =\u003E StartNewGame();\n\n\tpublic void StartNextLevel()\n\t{\n\t\tif ( HasNextLevel \u0026\u0026 LevelIndex \u003C HighestUnlockedLevel )\n\t\t\tLevelIndex\u002B\u002B;\n\n\t\tStartNewGame();\n\t}\n\n\tpublic void SelectPreviousLevel()\n\t{\n\t\tif ( CurrentState != GameState.Menu )\n\t\t\treturn;\n\n\t\tLevelIndex = Math.Max( 1, LevelIndex - 1 );\n\t\tApplyLevelSettings();\n\t\tBuildFreshBoard();\n\t}\n\n\tpublic void SelectNextLevel()\n\t{\n\t\tif ( CurrentState != GameState.Menu )\n\t\t\treturn;\n\n\t\tLevelIndex = Math.Min( LevelCount, LevelIndex \u002B 1 );\n\t\tApplyLevelSettings();\n\t\tBuildFreshBoard();\n\t}\n\n\tpublic void PauseGame()\n\t{\n\t\tif ( CurrentState == GameState.Playing )\n\t\t\tCurrentState = GameState.Paused;\n\t}\n\n\tpublic void ResumeGame()\n\t{\n\t\tif ( CurrentState == GameState.Paused )\n\t\t\tCurrentState = GameState.Playing;\n\t}\n\n\tpublic void QuitToMenu()\n\t{\n\t\tif ( IsEndless ) ApplyEndlessSettings();\n\t\telse ApplyLevelSettings();\n\t\tBuildFreshBoard();          // rebuild a fresh backdrop and reset stats\n\t\tCurrentState = GameState.Menu;\n\t}\n\n\tpublic void ToggleAudio() =\u003E AudioEnabled = !AudioEnabled;\n\tpublic void ToggleMusic() =\u003E MusicEnabled = !MusicEnabled;\n\tpublic void ToggleEffects() =\u003E EffectsEnabled = !EffectsEnabled;\n\tpublic void ToggleCameraShake() =\u003E CameraShakeEnabled = !CameraShakeEnabled;\n\tpublic void ToggleColourBlindMode()\n\t{\n\t\tColourBlindMode = !ColourBlindMode;\n\t\tRefreshAllPieceVisuals();\n\t}\n\n\t// -------------------- bug reporting --------------------\n\n\t// Reports are stored locally; only this Steam ID sees the in-game manager.\n\tconst long DevSteamId = 76561198271608270L;\n\n\tpublic bool IsDeveloper =\u003E LocalSteamId() == DevSteamId;\n\tpublic int OpenBugReportCount =\u003E ColourBreakBugReportStore.OpenCount();\n\n\tstatic long LocalSteamId()\n\t{\n\t\ttry { return Connection.Local?.SteamId.Value ?? 0L; }\n\t\tcatch { return 0L; }\n\t}\n\n\tstring LocalReporterName()\n\t{\n\t\ttry\n\t\t{\n\t\t\tvar c = Connection.Local;\n\t\t\tif ( c != null \u0026\u0026 !string.IsNullOrWhiteSpace( c.DisplayName ) )\n\t\t\t\treturn c.DisplayName;\n\t\t}\n\t\tcatch { }\n\t\treturn \u0022Player\u0022;\n\t}\n\n\tstring BugContext()\n\t{\n\t\tif ( IsEndless )\n\t\t\treturn $\u0022Endless - Score {_score}, Moves {_moves}\u0022;\n\t\treturn $\u0022Level {LevelIndex} ({LevelName}) - {CurrentState}\u0022;\n\t}\n\n\tpublic bool SubmitBugReport( string message )\n\t{\n\t\tif ( string.IsNullOrWhiteSpace( message ) )\n\t\t\treturn false;\n\n\t\tvar report = new ColourBreakBugReport\n\t\t{\n\t\t\tMessage = message,\n\t\t\tReporter = LocalReporterName(),\n\t\t\tSteamId = LocalSteamId(),\n\t\t\tContext = BugContext(),\n\t\t\tVersion = \u00221.0\u0022,\n\t\t};\n\n\t\tbool ok = ColourBreakBugReportStore.Add( report );\n\t\tif ( ok )\n\t\t\tPlayUiSound( ClearSound, 0.6f, 1.1f );\n\t\treturn ok;\n\t}\n\n\tpublic List\u003CColourBreakBugReport\u003E GetBugReports() =\u003E ColourBreakBugReportStore.GetAll();\n\tpublic void ResolveBugReport( string id ) =\u003E ColourBreakBugReportStore.SetResolved( id, true );\n\tpublic void ReopenBugReport( string id ) =\u003E ColourBreakBugReportStore.SetResolved( id, false );\n\tpublic void DeleteBugReport( string id ) =\u003E ColourBreakBugReportStore.Delete( id );\n\tpublic void ClearBugReports() =\u003E ColourBreakBugReportStore.Clear();\n\n\tvoid HandlePauseHotkeys()\n\t{\n\t\t// Esc toggles pause while in a game; ignored on the main menu.\n\t\tif ( CurrentState == GameState.Menu || CurrentState == GameState.Won || CurrentState == GameState.Lost ) return;\n\n\t\tif ( Pressed( \u0022Escape\u0022 ) || ActionPressed( \u0022menu\u0022, \u0022pause\u0022 ) )\n\t\t{\n\t\t\tif ( CurrentState == GameState.Playing ) PauseGame();\n\t\t\telse if ( CurrentState == GameState.Paused ) ResumeGame();\n\t\t}\n\t}\n\n\t// -------------------- environment --------------------\n\n\tvoid BuildEnvironment()\n\t{\n\t\tCleanupDecor();\n\n\t\tfloat boardW = Width * CellSpacing;\n\t\tfloat boardH = Height * CellSpacing;\n\t\tfloat edge = 18f;\n\t\tfloat depth = 28f;\n\n\t\tAddStageBackdrop( boardW, boardH, edge, depth );\n\n\t\t_decor.Add( CreateBlock( \u0022Tray\u0022,\n\t\t\tBoardOrigin \u002B new Vector3( 0f, depth * 0.5f \u002B 8f, 0f ),\n\t\t\tnew Vector3( boardW \u002B edge * 6.8f, depth, boardH \u002B edge * 6.8f ),\n\t\t\tnew Color( 0.025f, 0.028f, 0.050f ) ) );\n\n\t\tvar trayInner = CreateBlock( \u0022TrayInner\u0022,\n\t\t\tBoardOrigin \u002B new Vector3( 0f, depth * 0.5f \u002B 2f, 0f ),\n\t\t\tnew Vector3( boardW \u002B edge * 2.6f, depth - 4f, boardH \u002B edge * 2.6f ),\n\t\t\tnew Color( 0.055f, 0.065f, 0.105f ) );\n\t\t_trayInnerRenderer = trayInner.GetComponent\u003CModelRenderer\u003E();\n\t\t_trayBaseColor = new Color( 0.055f, 0.065f, 0.105f );\n\n\t\tfor ( int y = 0; y \u003C Height; y\u002B\u002B )\n\t\t{\n\t\t\tfor ( int x = 0; x \u003C Width; x\u002B\u002B )\n\t\t\t{\n\t\t\t\tfloat cellX = (x - (Width - 1) * 0.5f) * CellSpacing;\n\t\t\t\tfloat cellZ = (y - (Height - 1) * 0.5f) * CellSpacing;\n\t\t\t\tfloat alt = ((x \u002B y) \u0026 1) == 0 ? 0.00f : 0.018f;\n\t\t\t\tvar tile = CreateBlock( $\u0022WallTile_{x}_{y}\u0022,\n\t\t\t\t\tBoardOrigin \u002B new Vector3( cellX, depth * 0.5f - 2f, cellZ ),\n\t\t\t\t\tnew Vector3( CellSpacing * 0.86f, 3.5f, CellSpacing * 0.86f ),\n\t\t\t\t\tnew Color( 0.075f \u002B alt, 0.085f \u002B alt, 0.135f \u002B alt ) );\n\t\t\t\ttile.WorldRotation = Rotation.FromYaw( ((x \u002B y) % 3 - 1) * 1.4f );\n\t\t\t}\n\t\t}\n\n\t\tfor ( int x = 0; x \u003C= Width; x\u002B\u002B )\n\t\t{\n\t\t\tfloat gridX = (x - Width * 0.5f) * CellSpacing \u002B CellSpacing * 0.5f;\n\t\t\t_decor.Add( CreateBlock( $\u0022GridV_{x}\u0022,\n\t\t\t\tBoardOrigin \u002B new Vector3( gridX, depth * 0.5f - 5f, 0f ),\n\t\t\t\tnew Vector3( 1.2f, 1.8f, boardH \u002B edge * 0.6f ),\n\t\t\t\tnew Color( 0.025f, 0.22f, 0.34f ) ) );\n\t\t}\n\n\t\tfor ( int y = 0; y \u003C= Height; y\u002B\u002B )\n\t\t{\n\t\t\tfloat gridZ = (y - Height * 0.5f) * CellSpacing \u002B CellSpacing * 0.5f;\n\t\t\t_decor.Add( CreateBlock( $\u0022GridH_{y}\u0022,\n\t\t\t\tBoardOrigin \u002B new Vector3( 0f, depth * 0.5f - 5f, gridZ ),\n\t\t\t\tnew Vector3( boardW \u002B edge * 0.6f, 1.8f, 1.2f ),\n\t\t\t\tnew Color( 0.025f, 0.22f, 0.34f ) ) );\n\t\t}\n\n\t\tvar frameTint = new Color( 0.19f, 0.10f, 0.31f );\n\t\t_decor.Add( CreateBlock( \u0022FrameTop\u0022,\n\t\t\tBoardOrigin \u002B new Vector3( 0f, -4f, boardH * 0.5f \u002B edge * 1.0f ),\n\t\t\tnew Vector3( boardW \u002B edge * 5.2f, edge * 1.8f, edge * 1.8f ), frameTint ) );\n\t\t_decor.Add( CreateBlock( \u0022FrameBottom\u0022,\n\t\t\tBoardOrigin \u002B new Vector3( 0f, -4f, -boardH * 0.5f - edge * 1.0f ),\n\t\t\tnew Vector3( boardW \u002B edge * 5.2f, edge * 1.8f, edge * 1.8f ), frameTint ) );\n\t\t_decor.Add( CreateBlock( \u0022FrameLeft\u0022,\n\t\t\tBoardOrigin \u002B new Vector3( -boardW * 0.5f - edge * 1.0f, -4f, 0f ),\n\t\t\tnew Vector3( edge * 1.8f, edge * 1.8f, boardH \u002B edge * 5.2f ), frameTint ) );\n\t\t_decor.Add( CreateBlock( \u0022FrameRight\u0022,\n\t\t\tBoardOrigin \u002B new Vector3( boardW * 0.5f \u002B edge * 1.0f, -4f, 0f ),\n\t\t\tnew Vector3( edge * 1.8f, edge * 1.8f, boardH \u002B edge * 5.2f ), frameTint ) );\n\n\t\tvar railTint = new Color( 0.05f, 0.78f, 1f );\n\t\t_decor.Add( CreateBlock( \u0022GlowRailTop\u0022,\n\t\t\tBoardOrigin \u002B new Vector3( 0f, -12f, boardH * 0.5f \u002B edge * 2.2f ),\n\t\t\tnew Vector3( boardW \u002B edge * 4.6f, edge * 0.28f, edge * 0.30f ), railTint ) );\n\t\t_decor.Add( CreateBlock( \u0022GlowRailBottom\u0022,\n\t\t\tBoardOrigin \u002B new Vector3( 0f, -12f, -boardH * 0.5f - edge * 2.2f ),\n\t\t\tnew Vector3( boardW \u002B edge * 4.6f, edge * 0.28f, edge * 0.30f ), new Color( 1f, 0.28f, 0.05f ) ) );\n\t\t_decor.Add( CreateBlock( \u0022GlowRailLeft\u0022,\n\t\t\tBoardOrigin \u002B new Vector3( -boardW * 0.5f - edge * 2.2f, -12f, 0f ),\n\t\t\tnew Vector3( edge * 0.30f, edge * 0.28f, boardH \u002B edge * 4.6f ), new Color( 0.82f, 0.16f, 1f ) ) );\n\t\t_decor.Add( CreateBlock( \u0022GlowRailRight\u0022,\n\t\t\tBoardOrigin \u002B new Vector3( boardW * 0.5f \u002B edge * 2.2f, -12f, 0f ),\n\t\t\tnew Vector3( edge * 0.30f, edge * 0.28f, boardH \u002B edge * 4.6f ), new Color( 1f, 0.65f, 0.08f ) ) );\n\n\t\tAddPointLight( \u0022AccentL\u0022, BoardOrigin \u002B new Vector3( -boardW * 0.72f, -boardH * 0.50f, 118f ), new Color( 1f, 0.35f, 0.95f ), 1000f );\n\t\tAddPointLight( \u0022AccentR\u0022, BoardOrigin \u002B new Vector3( boardW * 0.72f, -boardH * 0.50f, 118f ), new Color( 0.25f, 0.92f, 1f ), 1000f );\n\t\tAddPointLight( \u0022AccentTop\u0022, BoardOrigin \u002B new Vector3( 0f, -boardH * 0.62f, boardH * 0.82f ), new Color( 1f, 0.85f, 0.48f ), 1200f );\n\n\t\t_orbitLightL = AddPointLightReturn( \u0022OrbitL\u0022, BoardOrigin, new Color( 1f, 0.28f, 0.08f ), 760f );\n\t\t_orbitLightR = AddPointLightReturn( \u0022OrbitR\u0022, BoardOrigin, new Color( 0.25f, 0.95f, 1f ), 760f );\n\n\t\t_decor.Add( CreateBlock( \u0022Floor\u0022,\n\t\t\tBoardOrigin \u002B new Vector3( 0f, depth \u002B 66f, -boardH * 0.5f - edge * 5.0f ),\n\t\t\tnew Vector3( boardW * 1.78f, 7f, edge * 7.0f ),\n\t\t\tnew Color( 0.018f, 0.020f, 0.035f ) ) );\n\n\t\tAddBottomCabinetLighting( boardW, boardH, edge );\n\t\tAddSideCabinetControls( -1, boardW, boardH, edge, new Color( 0.82f, 0.16f, 1f ), new Color( 1f, 0.55f, 0.08f ) );\n\t\tAddSideCabinetControls( 1, boardW, boardH, edge, new Color( 1f, 0.55f, 0.08f ), new Color( 0.05f, 0.78f, 1f ) );\n\t}\n\n\tGameObject CreateBlock( string name, Vector3 pos, Vector3 scale, Color tint )\n\t{\n\t\tvar go = new GameObject( true, name );\n\t\tgo.Flags = GameObjectFlags.NotNetworked;\n\t\tgo.WorldPosition = pos;\n\t\tgo.WorldScale = scale / 50f; // box.vmdl is ~50 units\n\t\tvar mr = go.AddComponent\u003CModelRenderer\u003E();\n\t\tmr.Model = _boxModel ?? CandyModel;\n\t\tmr.Tint = tint;\n\t\t_decor.Add( go );\n\t\treturn go;\n\t}\n\n\tvoid AddStageBackdrop( float boardW, float boardH, float edge, float depth )\n\t{\n\t\tfloat backY = depth \u002B 142f;\n\t\tvar backTint = new Color( 0.030f, 0.028f, 0.056f );\n\n\t\tCreateBlock( \u0022StageBackdrop\u0022,\n\t\t\tBoardOrigin \u002B new Vector3( 0f, backY, 0f ),\n\t\t\tnew Vector3( boardW * 3.25f, 10f, boardH * 2.45f ),\n\t\t\tbackTint );\n\n\t\tCreateBlock( \u0022StageBackdropCore\u0022,\n\t\t\tBoardOrigin \u002B new Vector3( 0f, backY - 6f, 0f ),\n\t\t\tnew Vector3( boardW * 1.55f, 6f, boardH * 1.55f ),\n\t\t\tnew Color( 0.050f, 0.055f, 0.090f ) );\n\n\t\tCreateBlock( \u0022StageLeftWing\u0022,\n\t\t\tBoardOrigin \u002B new Vector3( -boardW * 1.08f, backY - 3f, 0f ),\n\t\t\tnew Vector3( edge * 3.2f, 8f, boardH * 2.28f ),\n\t\t\tnew Color( 0.052f, 0.032f, 0.085f ) );\n\n\t\tCreateBlock( \u0022StageRightWing\u0022,\n\t\t\tBoardOrigin \u002B new Vector3( boardW * 1.08f, backY - 3f, 0f ),\n\t\t\tnew Vector3( edge * 3.2f, 8f, boardH * 2.28f ),\n\t\t\tnew Color( 0.030f, 0.060f, 0.088f ) );\n\n\t\tCreateBlock( \u0022StageTopLine\u0022,\n\t\t\tBoardOrigin \u002B new Vector3( 0f, backY - 8f, boardH * 0.78f ),\n\t\t\tnew Vector3( boardW * 2.25f, 4f, edge * 0.18f ),\n\t\t\tnew Color( 0.05f, 0.78f, 1f ) );\n\n\t\tCreateBlock( \u0022StageBottomLine\u0022,\n\t\t\tBoardOrigin \u002B new Vector3( 0f, backY - 8f, -boardH * 0.78f ),\n\t\t\tnew Vector3( boardW * 2.05f, 4f, edge * 0.18f ),\n\t\t\tnew Color( 1f, 0.34f, 0.06f ) );\n\n\t\tAddPointLight( \u0022StageWashLeft\u0022,\n\t\t\tBoardOrigin \u002B new Vector3( -boardW * 0.95f, depth - 36f, boardH * 0.12f ),\n\t\t\tnew Color( 0.75f, 0.18f, 1f ),\n\t\t\t900f );\n\n\t\tAddPointLight( \u0022StageWashRight\u0022,\n\t\t\tBoardOrigin \u002B new Vector3( boardW * 0.95f, depth - 36f, -boardH * 0.08f ),\n\t\t\tnew Color( 0.08f, 0.78f, 1f ),\n\t\t\t900f );\n\t}\n\n\tvoid AddSideCabinetControls( int side, float boardW, float boardH, float edge, Color ledTint, Color buttonTint )\n\t{\n\t\tstring label = side \u003C 0 ? \u0022Left\u0022 : \u0022Right\u0022;\n\t\tfloat x = side * (boardW * 0.5f \u002B edge * 1.28f);\n\t\tfloat y = -18.5f;\n\n\t\t_decor.Add( CreateBlock( $\u0022Cabinet{label}Inset\u0022,\n\t\t\tBoardOrigin \u002B new Vector3( x, y \u002B 0.4f, 0f ),\n\t\t\tnew Vector3( edge * 0.58f, edge * 0.52f, boardH * 0.74f ),\n\t\t\tnew Color( 0.075f, 0.045f, 0.115f ) ) );\n\n\t\t_decor.Add( CreateBlock( $\u0022Cabinet{label}LedRail\u0022,\n\t\t\tBoardOrigin \u002B new Vector3( x - side * edge * 0.18f, y - 4.2f, 0f ),\n\t\t\tnew Vector3( edge * 0.12f, edge * 0.12f, boardH * 0.70f ),\n\t\t\tledTint ) );\n\n\t\t_decor.Add( CreateBlock( $\u0022Cabinet{label}GoldTrimTop\u0022,\n\t\t\tBoardOrigin \u002B new Vector3( x - side * edge * 0.02f, y - 3.4f, boardH * 0.35f ),\n\t\t\tnew Vector3( edge * 0.42f, edge * 0.18f, edge * 0.12f ),\n\t\t\tnew Color( 1f, 0.72f, 0.22f ) ) );\n\t\t_decor.Add( CreateBlock( $\u0022Cabinet{label}GoldTrimBottom\u0022,\n\t\t\tBoardOrigin \u002B new Vector3( x - side * edge * 0.02f, y - 3.4f, -boardH * 0.35f ),\n\t\t\tnew Vector3( edge * 0.42f, edge * 0.18f, edge * 0.12f ),\n\t\t\tnew Color( 1f, 0.72f, 0.22f ) ) );\n\n\t\tAddSideButton( $\u0022Cabinet{label}ButtonTop\u0022, BoardOrigin \u002B new Vector3( x - side * edge * 0.03f, y - 5.0f, boardH * 0.22f ), buttonTint, 1.0f );\n\t\tAddSideButton( $\u0022Cabinet{label}ButtonBottom\u0022, BoardOrigin \u002B new Vector3( x - side * edge * 0.03f, y - 5.0f, -boardH * 0.18f ), Color.Lerp( buttonTint, Color.White, 0.24f ), 0.82f );\n\n\t\tAddPointLight( $\u0022Cabinet{label}SideGlow\u0022,\n\t\t\tBoardOrigin \u002B new Vector3( x - side * edge * 0.25f, y - 35f, 0f ),\n\t\t\tledTint,\n\t\t\t430f );\n\t}\n\n\tvoid AddBottomCabinetLighting( float boardW, float boardH, float edge )\n\t{\n\t\tfloat z = -boardH * 0.5f - edge * 1.12f;\n\t\tfloat y = -18.5f;\n\n\t\t_decor.Add( CreateBlock( \u0022CabinetBottomInset\u0022,\n\t\t\tBoardOrigin \u002B new Vector3( 0f, y \u002B 0.3f, z ),\n\t\t\tnew Vector3( boardW \u002B edge * 2.8f, edge * 0.48f, edge * 0.58f ),\n\t\t\tnew Color( 0.070f, 0.042f, 0.105f ) ) );\n\n\t\t_decor.Add( CreateBlock( \u0022CabinetBottomGoldRail\u0022,\n\t\t\tBoardOrigin \u002B new Vector3( 0f, y - 3.6f, z - edge * 0.24f ),\n\t\t\tnew Vector3( boardW \u002B edge * 2.4f, edge * 0.14f, edge * 0.14f ),\n\t\t\tnew Color( 1f, 0.68f, 0.18f ) ) );\n\n\t\t_decor.Add( CreateBlock( \u0022CabinetBottomGlowRail\u0022,\n\t\t\tBoardOrigin \u002B new Vector3( 0f, y - 4.8f, z \u002B edge * 0.18f ),\n\t\t\tnew Vector3( boardW \u002B edge * 1.7f, edge * 0.10f, edge * 0.12f ),\n\t\t\tnew Color( 1f, 0.33f, 0.05f ) ) );\n\n\t\tfor ( int i = 0; i \u003C 5; i\u002B\u002B )\n\t\t{\n\t\t\tfloat x = MathX.Lerp( -boardW * 0.42f, boardW * 0.42f, i / 4f );\n\t\t\tvar tint = i % 2 == 0 ? new Color( 1f, 0.48f, 0.08f ) : new Color( 0.05f, 0.78f, 1f );\n\t\t\tAddFooterLamp( $\u0022CabinetBottomLamp_{i}\u0022, BoardOrigin \u002B new Vector3( x, y - 5.4f, z \u002B edge * 0.02f ), tint );\n\t\t}\n\n\t\tAddPointLight( \u0022CabinetBottomGlow\u0022,\n\t\t\tBoardOrigin \u002B new Vector3( 0f, y - 38f, z \u002B edge * 0.10f ),\n\t\t\tnew Color( 1f, 0.42f, 0.08f ),\n\t\t\t520f );\n\t}\n\n\tvoid AddFooterLamp( string name, Vector3 pos, Color tint )\n\t{\n\t\tvar rim = new GameObject( true, $\u0022{name}Rim\u0022 );\n\t\trim.Flags = GameObjectFlags.NotNetworked;\n\t\trim.WorldPosition = pos;\n\t\trim.WorldScale = new Vector3( 0.105f, 0.024f, 0.105f );\n\t\tvar rimRenderer = rim.AddComponent\u003CModelRenderer\u003E();\n\t\trimRenderer.Model = _sphereModel ?? _boxModel ?? CandyModel;\n\t\trimRenderer.Tint = new Color( 0.40f, 0.42f, 0.50f );\n\t\t_decor.Add( rim );\n\n\t\tvar face = new GameObject( true, $\u0022{name}Face\u0022 );\n\t\tface.Flags = GameObjectFlags.NotNetworked;\n\t\tface.WorldPosition = pos \u002B new Vector3( 0f, -1.4f, 0f );\n\t\tface.WorldScale = new Vector3( 0.070f, 0.018f, 0.070f );\n\t\tvar faceRenderer = face.AddComponent\u003CModelRenderer\u003E();\n\t\tfaceRenderer.Model = _sphereModel ?? _boxModel ?? CandyModel;\n\t\tfaceRenderer.Tint = tint;\n\t\t_decor.Add( face );\n\t}\n\n\tvoid AddSideButton( string name, Vector3 pos, Color tint, float size )\n\t{\n\t\tvar rim = new GameObject( true, $\u0022{name}Rim\u0022 );\n\t\trim.Flags = GameObjectFlags.NotNetworked;\n\t\trim.WorldPosition = pos;\n\t\trim.WorldScale = new Vector3( 0.26f * size, 0.070f * size, 0.26f * size );\n\t\tvar rimRenderer = rim.AddComponent\u003CModelRenderer\u003E();\n\t\trimRenderer.Model = _sphereModel ?? _boxModel ?? CandyModel;\n\t\trimRenderer.Tint = new Color( 0.46f, 0.48f, 0.58f );\n\t\t_decor.Add( rim );\n\n\t\tvar face = new GameObject( true, $\u0022{name}Face\u0022 );\n\t\tface.Flags = GameObjectFlags.NotNetworked;\n\t\tface.WorldPosition = pos \u002B new Vector3( 0f, -2.4f, 0f );\n\t\tface.WorldScale = new Vector3( 0.18f * size, 0.050f * size, 0.18f * size );\n\t\tvar faceRenderer = face.AddComponent\u003CModelRenderer\u003E();\n\t\tfaceRenderer.Model = _sphereModel ?? _boxModel ?? CandyModel;\n\t\tfaceRenderer.Tint = tint;\n\t\t_decor.Add( face );\n\n\t\tvar shine = new GameObject( true, $\u0022{name}Shine\u0022 );\n\t\tshine.Flags = GameObjectFlags.NotNetworked;\n\t\tshine.WorldPosition = pos \u002B new Vector3( -3.4f * size, -4.2f, 4.2f * size );\n\t\tshine.WorldScale = new Vector3( 0.055f * size, 0.018f * size, 0.032f * size );\n\t\tvar shineRenderer = shine.AddComponent\u003CModelRenderer\u003E();\n\t\tshineRenderer.Model = _sphereModel ?? _boxModel ?? CandyModel;\n\t\tshineRenderer.Tint = new Color( 1f, 1f, 1f, 0.82f );\n\t\t_decor.Add( shine );\n\t}\n\n\tvoid AddPointLight( string name, Vector3 pos, Color color, float radius )\n\t{\n\t\tvar go = new GameObject( true, name );\n\t\tgo.Flags = GameObjectFlags.NotNetworked;\n\t\tgo.WorldPosition = pos;\n\t\tvar l = go.AddComponent\u003CPointLight\u003E();\n\t\tl.LightColor = color;\n\t\tl.Radius = radius;\n\t\t_decor.Add( go );\n\t}\n\n\tGameObject AddPointLightReturn( string name, Vector3 pos, Color color, float radius )\n\t{\n\t\tvar go = new GameObject( true, name );\n\t\tgo.Flags = GameObjectFlags.NotNetworked;\n\t\tgo.WorldPosition = pos;\n\t\tvar l = go.AddComponent\u003CPointLight\u003E();\n\t\tl.LightColor = color;\n\t\tl.Radius = radius;\n\t\t_decor.Add( go );\n\t\treturn go;\n\t}\n\n\t// -------------------- board --------------------\n\n\tvoid BuildFreshBoard()\n\t{\n\t\tClearBoardObjects();\n\n\t\t_types = new int[Width, Height];\n\t\t_specials = new SpecialKind[Width, Height];\n\t\t_visuals = new CandyVisual[Width, Height];\n\n\t\tint attempts = 0;\n\t\tdo\n\t\t{\n\t\t\tClearBoardObjects();\n\t\t\t_types = new int[Width, Height];\n\t\t\t_specials = new SpecialKind[Width, Height];\n\t\t\t_visuals = new CandyVisual[Width, Height];\n\t\t\tfor ( int y = 0; y \u003C Height; y\u002B\u002B )\n\t\t\t{\n\t\t\t\tfor ( int x = 0; x \u003C Width; x\u002B\u002B )\n\t\t\t\t{\n\t\t\t\t\tint type = PickTypeAvoidingImmediateMatch( x, y );\n\t\t\t\t\tSpawnCandy( x, y, type, instant: true );\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\twhile ( !HasPossibleMove() \u0026\u0026 \u002B\u002Battempts \u003C 20 );\n\n\t\t_cursorX = Width / 2;\n\t\t_cursorY = Height / 2;\n\t\t_hasSelection = false;\n\t\t_score = 0;\n\t\t_moves = 0;\n\t\t_objectiveProgress = 0;\n\t\t_phase = Phase.Idle;\n\t\t_idleTime = 0f;\n\t\t_hasHint = false;\n\t}\n\n\tvoid SpawnCandy( int x, int y, int type, bool instant )\n\t{\n\t\t_types[x, y] = type;\n\n\t\tvar anchor = CellToWorld( x, y );\n\t\tvar go = new GameObject( true, $\u0022Piece_{x}_{y}\u0022 );\n\t\tgo.Flags = GameObjectFlags.NotNetworked;\n\t\tgo.WorldRotation = Rotation.FromYaw( Game.Random.Float( -7f, 7f ) );\n\t\tvar renderer = go.AddComponent\u003CModelRenderer\u003E();\n\t\trenderer.Model = ModelForType( type );\n\t\tvar pieceColor = PieceColor( type );\n\t\trenderer.Tint = Color.Lerp( pieceColor, Color.Black, 0.28f );\n\n\t\tvar rim = AddPiecePart( go, $\u0022PieceRim_{x}_{y}\u0022, _sphereModel ?? _boxModel,\n\t\t\tnew Vector3( 0f, -4.0f, 0f ), new Vector3( 1.08f, 0.24f, 1.08f ), Color.Lerp( pieceColor, Color.Black, 0.42f ) );\n\t\tvar face = AddPiecePart( go, $\u0022PieceFace_{x}_{y}\u0022, _sphereModel ?? _boxModel,\n\t\t\tnew Vector3( 0f, -9.5f, 0.6f ), new Vector3( 0.76f, 0.14f, 0.76f ), Color.Lerp( pieceColor, Color.White, 0.20f ) );\n\t\tvar halo = AddPiecePart( go, $\u0022PieceHalo_{x}_{y}\u0022, _sphereModel ?? _boxModel,\n\t\t\tnew Vector3( 0f, -5.4f, 0f ), Vector3.Zero, new Color( 1f, 0.95f, 0.22f, 0.82f ) );\n\t\tvar guide = AddPiecePart( go, $\u0022PieceGuide_{x}_{y}\u0022, _sphereModel ?? _boxModel,\n\t\t\tnew Vector3( 0f, -5.0f, 0f ), Vector3.Zero, new Color( 0.22f, 0.92f, 1f, 0.62f ) );\n\t\tvar accent = AddPiecePart( go, $\u0022PieceAccent_{x}_{y}\u0022, _boxModel ?? _sphereModel,\n\t\t\tnew Vector3( 0f, -13.0f, 7.0f ), new Vector3( 0.34f, 0.034f, 0.048f \u002B (type % 3) * 0.020f ), Color.Lerp( pieceColor, Color.White, 0.70f ) );\n\t\taccent.LocalRotation = Rotation.FromYaw( type * 28f );\n\t\tvar symbolA = AddPiecePart( go, $\u0022PieceSymbolA_{x}_{y}\u0022, _boxModel ?? _sphereModel,\n\t\t\tnew Vector3( 0f, -18.0f, 0.0f ), Vector3.Zero, new Color( 0.02f, 0.025f, 0.035f, 1f ) );\n\t\tvar symbolB = AddPiecePart( go, $\u0022PieceSymbolB_{x}_{y}\u0022, _boxModel ?? _sphereModel,\n\t\t\tnew Vector3( 0f, -18.4f, 0.0f ), Vector3.Zero, new Color( 1f, 1f, 1f, 1f ) );\n\t\tvar shine = AddPiecePart( go, $\u0022PieceShine_{x}_{y}\u0022, _sphereModel ?? _boxModel,\n\t\t\tnew Vector3( -8.5f, -14.0f, 9.0f ), new Vector3( 0.16f, 0.026f, 0.080f ), new Color( 1f, 1f, 1f, 0.86f ) );\n\t\tvar badge = AddPiecePart( go, $\u0022PieceSpecial_{x}_{y}\u0022, _boxModel ?? _sphereModel,\n\t\t\tnew Vector3( 0f, -15.0f, -8.0f ), Vector3.Zero, new Color( 1f, 0.82f, 0.18f, 1f ) );\n\n\t\tvar v = new CandyVisual\n\t\t{\n\t\t\tGo = go,\n\t\t\tRenderer = renderer,\n\t\t\tShine = shine,\n\t\t\tShineRenderer = shine.GetComponent\u003CModelRenderer\u003E(),\n\t\t\tRim = rim,\n\t\t\tRimRenderer = rim.GetComponent\u003CModelRenderer\u003E(),\n\t\t\tFace = face,\n\t\t\tFaceRenderer = face.GetComponent\u003CModelRenderer\u003E(),\n\t\t\tHalo = halo,\n\t\t\tHaloRenderer = halo.GetComponent\u003CModelRenderer\u003E(),\n\t\t\tGuide = guide,\n\t\t\tGuideRenderer = guide.GetComponent\u003CModelRenderer\u003E(),\n\t\t\tAccent = accent,\n\t\t\tAccentRenderer = accent.GetComponent\u003CModelRenderer\u003E(),\n\t\t\tSymbolA = symbolA,\n\t\t\tSymbolARenderer = symbolA.GetComponent\u003CModelRenderer\u003E(),\n\t\t\tSymbolB = symbolB,\n\t\t\tSymbolBRenderer = symbolB.GetComponent\u003CModelRenderer\u003E(),\n\t\t\tSpecialBadge = badge,\n\t\t\tSpecialBadgeRenderer = badge.GetComponent\u003CModelRenderer\u003E(),\n\t\t\tType = type,\n\t\t\tSpecial = SpecialKind.None,\n\t\t\tAnchor = anchor,\n\t\t\tBobPhase = Game.Random.Float( 0f, MathF.PI * 2f ),\n\t\t\tSpawning = !instant,\n\t\t\tSpawnTimer = instant ? 0f : 0.25f,\n\t\t};\n\n\t\tif ( instant )\n\t\t{\n\t\t\tgo.WorldPosition = anchor;\n\t\t\tgo.WorldScale = Vector3.One * CandyScale * PieceShape( type );\n\t\t}\n\t\telse\n\t\t{\n\t\t\tgo.WorldPosition = anchor \u002B new Vector3( 0f, 0f, Height * CellSpacing * 0.6f \u002B Game.Random.Float( 0f, 60f ) );\n\t\t\tgo.WorldScale = Vector3.One * CandyScale * PieceShape( type ) * 0.4f;\n\t\t}\n\n\t\t_visuals[x, y] = v;\n\t\tApplyPieceVisualStyle( v );\n\t}\n\n\tGameObject AddPiecePart( GameObject parent, string name, Model model, Vector3 localPosition, Vector3 localScale, Color tint )\n\t{\n\t\tvar part = new GameObject( true, name );\n\t\tpart.Flags = GameObjectFlags.NotNetworked;\n\t\tpart.SetParent( parent, false );\n\t\tpart.LocalPosition = localPosition;\n\t\tpart.LocalScale = localScale;\n\t\tvar mr = part.AddComponent\u003CModelRenderer\u003E();\n\t\tmr.Model = model;\n\t\tmr.Tint = tint;\n\t\treturn part;\n\t}\n\n\tvoid ApplyPieceVisualStyle( CandyVisual v )\n\t{\n\t\tif ( v == null ) return;\n\n\t\tvar color = PieceColor( v.Type );\n\t\tif ( v.Renderer != null ) v.Renderer.Tint = Color.Lerp( color, Color.Black, 0.28f );\n\t\tif ( v.RimRenderer != null ) v.RimRenderer.Tint = Color.Lerp( color, Color.Black, 0.42f );\n\t\tif ( v.FaceRenderer != null ) v.FaceRenderer.Tint = Color.Lerp( color, Color.White, 0.20f );\n\t\tif ( v.AccentRenderer != null ) v.AccentRenderer.Tint = Color.Lerp( color, Color.White, 0.70f );\n\n\t\tApplyColourBlindSymbol( v );\n\t}\n\n\tvoid ApplyColourBlindSymbol( CandyVisual v )\n\t{\n\t\tif ( v?.SymbolA == null || v.SymbolB == null )\n\t\t\treturn;\n\n\t\tif ( !ColourBlindMode )\n\t\t{\n\t\t\tv.SymbolA.LocalScale = Vector3.Zero;\n\t\t\tv.SymbolB.LocalScale = Vector3.Zero;\n\t\t\treturn;\n\t\t}\n\n\t\tv.SymbolA.LocalRotation = Rotation.Identity;\n\t\tv.SymbolB.LocalRotation = Rotation.Identity;\n\t\tv.SymbolA.LocalScale = Vector3.Zero;\n\t\tv.SymbolB.LocalScale = Vector3.Zero;\n\t\tif ( v.SymbolARenderer != null ) v.SymbolARenderer.Tint = new Color( 0.02f, 0.025f, 0.035f, 1f );\n\t\tif ( v.SymbolBRenderer != null ) v.SymbolBRenderer.Tint = new Color( 1f, 1f, 1f, 1f );\n\n\t\tswitch ( v.Type )\n\t\t{\n\t\t\tcase 0:\n\t\t\t\tv.SymbolB.LocalScale = new Vector3( 0.19f, 0.036f, 0.70f );\n\t\t\t\tv.SymbolA.LocalScale = new Vector3( 0.11f, 0.040f, 0.58f );\n\t\t\t\tbreak;\n\t\t\tcase 1:\n\t\t\t\tv.SymbolB.LocalScale = new Vector3( 0.70f, 0.036f, 0.19f );\n\t\t\t\tv.SymbolA.LocalScale = new Vector3( 0.58f, 0.040f, 0.11f );\n\t\t\t\tbreak;\n\t\t\tcase 2:\n\t\t\t\tv.SymbolB.LocalScale = new Vector3( 0.68f, 0.036f, 0.17f );\n\t\t\t\tv.SymbolB.LocalRotation = Rotation.FromYaw( 45f );\n\t\t\t\tv.SymbolA.LocalScale = new Vector3( 0.56f, 0.040f, 0.10f );\n\t\t\t\tv.SymbolA.LocalRotation = Rotation.FromYaw( 45f );\n\t\t\t\tbreak;\n\t\t\tcase 3:\n\t\t\t\tv.SymbolA.LocalScale = new Vector3( 0.60f, 0.040f, 0.12f );\n\t\t\t\tv.SymbolB.LocalScale = new Vector3( 0.12f, 0.042f, 0.60f );\n\t\t\t\tbreak;\n\t\t\tcase 4:\n\t\t\t\tv.SymbolB.LocalScale = new Vector3( 0.42f, 0.036f, 0.42f );\n\t\t\t\tv.SymbolA.LocalScale = new Vector3( 0.30f, 0.040f, 0.30f );\n\t\t\t\tbreak;\n\t\t\tdefault:\n\t\t\t\tv.SymbolA.LocalScale = new Vector3( 0.60f, 0.040f, 0.12f );\n\t\t\t\tv.SymbolA.LocalRotation = Rotation.FromYaw( -45f );\n\t\t\t\tv.SymbolB.LocalScale = new Vector3( 0.60f, 0.042f, 0.12f );\n\t\t\t\tv.SymbolB.LocalRotation = Rotation.FromYaw( 45f );\n\t\t\t\tbreak;\n\t\t}\n\t}\n\n\tvoid RefreshAllPieceVisuals()\n\t{\n\t\tif ( _visuals == null ) return;\n\n\t\tfor ( int y = 0; y \u003C _visuals.GetLength( 1 ); y\u002B\u002B )\n\t\t\tfor ( int x = 0; x \u003C _visuals.GetLength( 0 ); x\u002B\u002B )\n\t\t\t\tApplyPieceVisualStyle( _visuals[x, y] );\n\t}\n\n\tvoid RemoveCandyAt( int x, int y )\n\t{\n\t\tvar v = _visuals[x, y];\n\t\tv?.Go?.Destroy();\n\t\t_visuals[x, y] = null;\n\t}\n\n\tVector3 CellToWorld( int x, int y )\n\t{\n\t\tfloat ox = (x - (Width - 1) * 0.5f) * CellSpacing;\n\t\tfloat oz = (y - (Height - 1) * 0.5f) * CellSpacing;\n\t\treturn BoardOrigin \u002B new Vector3( ox, 0f, oz );\n\t}\n\n\t// -------------------- input --------------------\n\n\tbool TryHitBoardCell( out int cx, out int cy )\n\t{\n\t\tcx = cy = -1;\n\t\tif ( !TryGetMainCamera( out var cam ) ) return false;\n\n\t\tvar ray = cam.ScreenPixelToRay( Mouse.Position );\n\t\tfloat planeY = BoardOrigin.y;\n\t\tfloat denom = ray.Forward.y;\n\t\tif ( MathF.Abs( denom ) \u003C 0.0001f ) return false;\n\t\tfloat t = (planeY - ray.Position.y) / denom;\n\t\tif ( t \u003C= 0 ) return false;\n\n\t\tvar hit = ray.Position \u002B ray.Forward * t;\n\t\tfloat localX = hit.x - BoardOrigin.x \u002B (Width - 1) * 0.5f * CellSpacing;\n\t\tfloat localZ = hit.z - BoardOrigin.z \u002B (Height - 1) * 0.5f * CellSpacing;\n\t\tint tx = (int)MathF.Floor( localX / CellSpacing \u002B 0.5f );\n\t\tint ty = (int)MathF.Floor( localZ / CellSpacing \u002B 0.5f );\n\t\tif ( tx \u003C 0 || tx \u003E= Width || ty \u003C 0 || ty \u003E= Height ) return false;\n\t\tcx = tx; cy = ty;\n\t\treturn true;\n\t}\n\n\tvoid HandleMouse()\n\t{\n\t\tbool overBoard = TryHitBoardCell( out int cx, out int cy );\n\t\tif ( overBoard )\n\t\t{\n\t\t\tif ( cx != _cursorX || cy != _cursorY )\n\t\t\t\tResetIdle();\n\t\t\t_cursorX = cx;\n\t\t\t_cursorY = cy;\n\t\t}\n\n\t\tbool mouseLeft = Input.Down( \u0022attack1\u0022 );\n\t\tbool justPressed = mouseLeft \u0026\u0026 !_prevMouseLeft;\n\t\tbool justReleased = !mouseLeft \u0026\u0026 _prevMouseLeft;\n\t\t_prevMouseLeft = mouseLeft;\n\n\t\tif ( overBoard \u0026\u0026 (cx != _cursorX || cy != _cursorY) )\n\t\t\tResetIdle();\n\n\t\tif ( justPressed \u0026\u0026 overBoard )\n\t\t{\n\t\t\tResetIdle();\n\t\t\t_dragging = true;\n\t\t\t_dragSwapped = false;\n\t\t\t_dragStartX = cx;\n\t\t\t_dragStartY = cy;\n\t\t\t_selectedX = cx;\n\t\t\t_selectedY = cy;\n\t\t\t_hasSelection = true;\n\t\t\tSpawnShockwave( CellToWorld( cx, cy ), new Color( 1f, 1f, 1f ), 0.28f, 26f );\n\t\t\treturn;\n\t\t}\n\n\t\tif ( _dragging \u0026\u0026 mouseLeft \u0026\u0026 overBoard \u0026\u0026 !_dragSwapped )\n\t\t{\n\t\t\tif ( (cx != _dragStartX || cy != _dragStartY) \u0026\u0026 AreAdjacent( _dragStartX, _dragStartY, cx, cy ) )\n\t\t\t{\n\t\t\t\tBeginSwap( _dragStartX, _dragStartY, cx, cy );\n\t\t\t\t_dragSwapped = true;\n\t\t\t\t_hasSelection = false;\n\t\t\t}\n\t\t}\n\n\t\tif ( justReleased )\n\t\t{\n\t\t\t_dragging = false;\n\t\t}\n\t}\n\n\tvoid HandleInput()\n\t{\n\t\tif ( Pressed( \u0022r\u0022 ) || ActionPressed( \u0022reload\u0022 ) )\n\t\t{\n\t\t\tBuildFreshBoard();\n\t\t\tLog.Info( \u0022Board reset.\u0022 );\n\t\t\treturn;\n\t\t}\n\n\t\tif ( PressedEither( \u0022ArrowUp\u0022, \u0022w\u0022 ) ) _cursorY = Math.Min( Height - 1, _cursorY \u002B 1 );\n\t\tif ( PressedEither( \u0022ArrowDown\u0022, \u0022s\u0022 ) ) _cursorY = Math.Max( 0, _cursorY - 1 );\n\t\tif ( PressedEither( \u0022ArrowLeft\u0022, \u0022a\u0022 ) ) _cursorX = Math.Max( 0, _cursorX - 1 );\n\t\tif ( PressedEither( \u0022ArrowRight\u0022, \u0022d\u0022 ) ) _cursorX = Math.Min( Width - 1, _cursorX \u002B 1 );\n\t\tHandleControllerCursor();\n\n\t\tif ( Pressed( \u0022Space\u0022 ) || Pressed( \u0022Enter\u0022 ) || Pressed( \u0022e\u0022 ) || ActionPressed( \u0022jump\u0022, \u0022use\u0022, \u0022attack1\u0022 ) )\n\t\t\tHandleSelectKey();\n\n\t\tif ( _hasSelection \u0026\u0026 ActionPressed( \u0022attack2\u0022, \u0022duck\u0022 ) )\n\t\t\t_hasSelection = false;\n\t}\n\n\tvoid HandleControllerCursor()\n\t{\n\t\tif ( !Input.UsingController \u0026\u0026 Input.ControllerCount \u003C= 0 )\n\t\t\treturn;\n\n\t\tif ( _controllerMoveCooldown \u003E 0f )\n\t\t\treturn;\n\n\t\tvar move = Input.AnalogMove;\n\t\tfloat ax = move.x;\n\t\tfloat ay = move.y;\n\t\tconst float threshold = 0.45f;\n\t\tbool moved = false;\n\n\t\tif ( MathF.Abs( ax ) \u003E MathF.Abs( ay ) \u0026\u0026 MathF.Abs( ax ) \u003E threshold )\n\t\t{\n\t\t\t_cursorX = Math.Clamp( _cursorX \u002B (ax \u003E 0f ? 1 : -1), 0, Width - 1 );\n\t\t\tmoved = true;\n\t\t}\n\t\telse if ( MathF.Abs( ay ) \u003E threshold )\n\t\t{\n\t\t\t_cursorY = Math.Clamp( _cursorY \u002B (ay \u003E 0f ? 1 : -1), 0, Height - 1 );\n\t\t\tmoved = true;\n\t\t}\n\n\t\tif ( moved )\n\t\t\t_controllerMoveCooldown = 0.16f;\n\t}\n\n\tvoid HandleSelectKey()\n\t{\n\t\tif ( !_hasSelection )\n\t\t{\n\t\t\t_selectedX = _cursorX;\n\t\t\t_selectedY = _cursorY;\n\t\t\t_hasSelection = true;\n\t\t\tSpawnShockwave( CellToWorld( _cursorX, _cursorY ), new Color( 1f, 1f, 1f ), 0.28f, 26f );\n\t\t\treturn;\n\t\t}\n\t\tif ( _selectedX == _cursorX \u0026\u0026 _selectedY == _cursorY )\n\t\t{\n\t\t\t_hasSelection = false;\n\t\t\treturn;\n\t\t}\n\t\tif ( !AreAdjacent( _selectedX, _selectedY, _cursorX, _cursorY ) )\n\t\t{\n\t\t\tSpawnShockwave( CellToWorld( _cursorX, _cursorY ), new Color( 0.22f, 0.92f, 1f ), 0.22f, 18f );\n\t\t\t_selectedX = _cursorX;\n\t\t\t_selectedY = _cursorY;\n\t\t\treturn;\n\t\t}\n\t\tBeginSwap( _selectedX, _selectedY, _cursorX, _cursorY );\n\t\t_hasSelection = false;\n\t}\n\n\t// -------------------- hint system --------------------\n\n\tvoid ResetIdle()\n\t{\n\t\t_idleTime = 0f;\n\t\t_hasHint = false;\n\t}\n\n\tvoid UpdateHint()\n\t{\n\t\t// Hints only make sense while the player can actually act on the board.\n\t\tif ( CurrentState != GameState.Playing || _phase != Phase.Idle || _hasSelection )\n\t\t{\n\t\t\t_idleTime = 0f;\n\t\t\t_hasHint = false;\n\t\t\treturn;\n\t\t}\n\n\t\t_idleTime \u002B= Time.Delta;\n\t\tif ( _idleTime \u003C HintDelay )\n\t\t{\n\t\t\t_hasHint = false;\n\t\t\treturn;\n\t\t}\n\n\t\tif ( !_hasHint )\n\t\t\t_hasHint = FindHintMove( out _hintAX, out _hintAY, out _hintBX, out _hintBY );\n\t}\n\n\tbool FindHintMove( out int ax, out int ay, out int bx, out int by )\n\t{\n\t\tax = ay = bx = by = -1;\n\t\tif ( _types == null ) return false;\n\n\t\t// Prefer activating an existing special if one is on the board.\n\t\tfor ( int y = 0; y \u003C Height; y\u002B\u002B )\n\t\t{\n\t\t\tfor ( int x = 0; x \u003C Width; x\u002B\u002B )\n\t\t\t{\n\t\t\t\tif ( _specials != null \u0026\u0026 _specials[x, y] != SpecialKind.None )\n\t\t\t\t{\n\t\t\t\t\tif ( x \u002B 1 \u003C Width ) { ax = x; ay = y; bx = x \u002B 1; by = y; return true; }\n\t\t\t\t\tif ( y \u002B 1 \u003C Height ) { ax = x; ay = y; bx = x; by = y \u002B 1; return true; }\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tfor ( int y = 0; y \u003C Height; y\u002B\u002B )\n\t\t{\n\t\t\tfor ( int x = 0; x \u003C Width; x\u002B\u002B )\n\t\t\t{\n\t\t\t\tif ( x \u002B 1 \u003C Width \u0026\u0026 SwapWouldMatch( x, y, x \u002B 1, y ) ) { ax = x; ay = y; bx = x \u002B 1; by = y; return true; }\n\t\t\t\tif ( y \u002B 1 \u003C Height \u0026\u0026 SwapWouldMatch( x, y, x, y \u002B 1 ) ) { ax = x; ay = y; bx = x; by = y \u002B 1; return true; }\n\t\t\t}\n\t\t}\n\t\treturn false;\n\t}\n\n\t// -------------------- phase machine --------------------\n\n\tvoid BeginSwap( int x1, int y1, int x2, int y2 )\n\t{\n\t\t_hasEverSwapped = true;\n\t\tResetIdle();\n\t\tPlayUiSound( SwapSound, 0.55f, 0.95f \u002B Game.Random.Float( 0f, 0.12f ) );\n\t\t_swapAX = x1; _swapAY = y1; _swapBX = x2; _swapBY = y2;\n\t\tStartSwapTween( x1, y1, x2, y2 );\n\t\t_phase = Phase.SwapForward;\n\t\t_phaseTimer = 0f;\n\t}\n\n\tvoid StartSwapTween( int x1, int y1, int x2, int y2 )\n\t{\n\t\tvar a = _visuals[x1, y1];\n\t\tvar b = _visuals[x2, y2];\n\t\tif ( a == null || b == null ) return;\n\n\t\tvar posA = CellToWorld( x1, y1 );\n\t\tvar posB = CellToWorld( x2, y2 );\n\t\ta.SwapFrom = a.Go.WorldPosition; a.SwapTo = posB; a.SwapT = 0f; a.Swapping = true; a.Anchor = posB;\n\t\tb.SwapFrom = b.Go.WorldPosition; b.SwapTo = posA; b.SwapT = 0f; b.Swapping = true; b.Anchor = posA;\n\n\t\t// Update the logical board now so subsequent logic is correct\n\t\t(_types[x1, y1], _types[x2, y2]) = (_types[x2, y2], _types[x1, y1]);\n\t\t(_specials[x1, y1], _specials[x2, y2]) = (_specials[x2, y2], _specials[x1, y1]);\n\t\t(_visuals[x1, y1], _visuals[x2, y2]) = (_visuals[x2, y2], _visuals[x1, y1]);\n\t}\n\n\tvoid UpdatePhase()\n\t{\n\t\t_phaseTimer \u002B= Time.Delta;\n\n\t\tswitch ( _phase )\n\t\t{\n\t\t\tcase Phase.Idle: return;\n\n\t\t\tcase Phase.SwapForward:\n\t\t\t\tif ( _phaseTimer \u003E= SwapDuration )\n\t\t\t\t{\n\t\t\t\t\tvar matches = FindMatches();\n\t\t\t\t\tvar specialActivation = GetSpecialActivationForSwap();\n\t\t\t\t\tforeach ( var idx in specialActivation )\n\t\t\t\t\t\tmatches.Add( idx );\n\n\t\t\t\t\tif ( matches.Count == 0 )\n\t\t\t\t\t{\n\t\t\t\t\t\tPlayUiSound( DeniedSound, 0.55f, 0.82f );\n\t\t\t\t\t\tSpawnShockwave( (CellToWorld( _swapAX, _swapAY ) \u002B CellToWorld( _swapBX, _swapBY )) * 0.5f, new Color( 1f, 0.18f, 0.06f ), 0.34f, 52f );\n\t\t\t\t\t\tPunchCamera( 1.0f, 0.85f );\n\t\t\t\t\t\t// Swap back\n\t\t\t\t\t\tStartSwapTween( _swapAX, _swapAY, _swapBX, _swapBY );\n\t\t\t\t\t\t_phase = Phase.SwapBack;\n\t\t\t\t\t\t_phaseTimer = 0f;\n\t\t\t\t\t}\n\t\t\t\t\telse\n\t\t\t\t\t{\n\t\t\t\t\t\t_moves\u002B\u002B;\n\t\t\t\t\t\t_comboCount = 1;\n\t\t\t\t\t\tBeginClear( matches );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tbreak;\n\n\t\t\tcase Phase.SwapBack:\n\t\t\t\tif ( _phaseTimer \u003E= SwapDuration )\n\t\t\t\t{\n\t\t\t\t\t_phase = Phase.Idle;\n\t\t\t\t\t_phaseTimer = 0f;\n\t\t\t\t}\n\t\t\t\tbreak;\n\n\t\t\tcase Phase.Clearing:\n\t\t\t\tif ( AllClearAnimsDone() )\n\t\t\t\t{\n\t\t\t\t\tDestroyClearedCandies();\n\t\t\t\t\t_phase = Phase.Collapsing;\n\t\t\t\t\t_phaseTimer = 0f;\n\t\t\t\t\tCollapseColumns();\n\t\t\t\t}\n\t\t\t\tbreak;\n\n\t\t\tcase Phase.Collapsing:\n\t\t\t\tif ( AllAtAnchor() )\n\t\t\t\t{\n\t\t\t\t\t_phase = Phase.Refilling;\n\t\t\t\t\t_phaseTimer = 0f;\n\t\t\t\t\tRefill();\n\t\t\t\t}\n\t\t\t\tbreak;\n\n\t\t\tcase Phase.Refilling:\n\t\t\t\tif ( AllAtAnchor() )\n\t\t\t\t{\n\t\t\t\t\t_phase = Phase.Pause;\n\t\t\t\t\t_phaseTimer = 0f;\n\t\t\t\t}\n\t\t\t\tbreak;\n\n\t\t\tcase Phase.Pause:\n\t\t\t\tif ( _phaseTimer \u003E= CascadePause )\n\t\t\t\t{\n\t\t\t\t\tvar matches = FindMatches();\n\t\t\t\t\tif ( matches.Count \u003E 0 )\n\t\t\t\t\t{\n\t\t\t\t\t\t_comboCount\u002B\u002B;\n\t\t\t\t\t\tBeginClear( matches );\n\t\t\t\t\t}\n\t\t\t\t\telse\n\t\t\t\t\t{\n\t\t\t\t\t\t_phase = Phase.Idle;\n\t\t\t\t\t\tCheckLevelEnd();\n\t\t\t\t\t\tif ( CurrentState == GameState.Playing \u0026\u0026 !HasPossibleMove() )\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t// Levels rescue the player with a reshuffle; endless ends\n\t\t\t\t\t\t\t// precisely when there is nothing left to match.\n\t\t\t\t\t\t\tif ( IsEndless )\n\t\t\t\t\t\t\t\tEndEndlessRun();\n\t\t\t\t\t\t\telse\n\t\t\t\t\t\t\t\tReshuffleBoardForAvailableMove();\n\t\t\t\t\t\t}\n\t\t\t\t\t\tLog.Info( $\u0022Score: {_score} | Moves: {_moves}\u0022 );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t}\n\t}\n\n\tvoid BeginClear( HashSet\u003Cint\u003E matches )\n\t{\n\t\tbool activatingSpecial = ContainsSpecial( matches );\n\t\tint triggeredSpecials = CountSpecialsInCells( matches );\n\t\tvar rewardKind = SpecialKind.None;\n\t\tint rewardIdx = -1;\n\t\tif ( !activatingSpecial )\n\t\t\tTryChooseSpecialReward( matches, out rewardIdx, out rewardKind );\n\n\t\tExpandSpecialClears( matches );\n\t\tif ( rewardIdx \u003E= 0 \u0026\u0026 matches.Count \u003E 3 )\n\t\t\tmatches.Remove( rewardIdx );\n\n\t\tTrackObjectiveProgress( matches, rewardKind, triggeredSpecials );\n\t\t_score \u002B= matches.Count * 10 * _comboCount \u002B (activatingSpecial ? 75 * _comboCount : 0);\n\t\tPlayUiSound( _comboCount \u003E 1 ? ComboSound : ClearSound, MathF.Min( 1f, 0.55f \u002B _comboCount * 0.12f ), 0.95f \u002B _comboCount * 0.06f );\n\t\tvar center = Vector3.Zero;\n\t\tint centerCount = 0;\n\n\t\tif ( rewardIdx \u003E= 0 \u0026\u0026 rewardKind != SpecialKind.None )\n\t\t{\n\t\t\tint sx = rewardIdx % Width;\n\t\t\tint sy = rewardIdx / Width;\n\t\t\tSetSpecialAt( sx, sy, rewardKind );\n\t\t\tvar specialVisual = _visuals[sx, sy];\n\t\t\tif ( specialVisual != null )\n\t\t\t{\n\t\t\t\tSpawnShockwave( specialVisual.Go.WorldPosition, new Color( 1f, 0.88f, 0.18f ), 0.52f, 72f );\n\t\t\t\tSpawnFireColumn( specialVisual.Go.WorldPosition, 0.65f );\n\t\t\t}\n\t\t}\n\n\t\tforeach ( var idx in matches )\n\t\t{\n\t\t\tint x = idx % Width;\n\t\t\tint y = idx / Width;\n\t\t\tvar v = _visuals[x, y];\n\t\t\tif ( v == null ) continue;\n\t\t\tv.Clearing = true;\n\t\t\tv.ClearTimer = ClearDuration;\n\t\t\t_specials[x, y] = SpecialKind.None;\n\t\t\tvar clearColor = PieceColor( v.Type );\n\t\t\tSpawnBurstAt( v.Go.WorldPosition, clearColor );\n\t\t\tSpawnShockwave( v.Go.WorldPosition, clearColor, 0.34f, 38f \u002B _comboCount * 10f );\n\t\t\tcenter \u002B= v.Go.WorldPosition;\n\t\t\tcenterCount\u002B\u002B;\n\t\t}\n\t\tif ( centerCount \u003E 0 )\n\t\t{\n\t\t\tSpawnFireColumn( center / centerCount, MathF.Min( 1.8f, 1f \u002B matches.Count * 0.05f \u002B _comboCount * 0.18f ) );\n\t\t\tSpawnShockwave( center / centerCount, Color.White, 0.48f, 70f \u002B matches.Count * 4f );\n\t\t}\n\t\t// Camera punch scales with combo size and chain depth\n\t\tfloat punchFov = MathF.Min( 8f, 2.5f \u002B matches.Count * 0.3f \u002B _comboCount * 1.2f );\n\t\tfloat punchShake = MathF.Min( 6f, 1.5f \u002B _comboCount * 0.8f );\n\t\tPunchCamera( punchFov, punchShake );\n\t\t_phase = Phase.Clearing;\n\t\t_phaseTimer = 0f;\n\t}\n\n\tHashSet\u003Cint\u003E GetSpecialActivationForSwap()\n\t{\n\t\tvar result = new HashSet\u003Cint\u003E();\n\t\tAddSpecialCells( _swapAX, _swapAY, result );\n\t\tAddSpecialCells( _swapBX, _swapBY, result );\n\t\treturn result;\n\t}\n\n\tbool ContainsSpecial( HashSet\u003Cint\u003E cells )\n\t{\n\t\tforeach ( var idx in cells )\n\t\t{\n\t\t\tint x = idx % Width;\n\t\t\tint y = idx / Width;\n\t\t\tif ( InBounds( x, y ) \u0026\u0026 _specials[x, y] != SpecialKind.None )\n\t\t\t\treturn true;\n\t\t}\n\t\treturn false;\n\t}\n\n\tint CountSpecialsInCells( HashSet\u003Cint\u003E cells )\n\t{\n\t\tint count = 0;\n\t\tforeach ( var idx in cells )\n\t\t{\n\t\t\tint x = idx % Width;\n\t\t\tint y = idx / Width;\n\t\t\tif ( InBounds( x, y ) \u0026\u0026 _specials[x, y] != SpecialKind.None )\n\t\t\t\tcount\u002B\u002B;\n\t\t}\n\t\treturn count;\n\t}\n\n\tvoid TrackObjectiveProgress( HashSet\u003Cint\u003E clearedCells, SpecialKind rewardKind, int triggeredSpecials )\n\t{\n\t\tif ( !HasSecondaryObjective )\n\t\t\treturn;\n\n\t\tvar level = CurrentLevelDefinition;\n\t\tint add = 0;\n\t\tswitch ( level.ObjectiveKind )\n\t\t{\n\t\t\tcase ColourBreakObjectiveKind.ClearPieces:\n\t\t\t\tadd = clearedCells.Count;\n\t\t\t\tbreak;\n\t\t\tcase ColourBreakObjectiveKind.ClearColour:\n\t\t\t\tforeach ( var idx in clearedCells )\n\t\t\t\t{\n\t\t\t\t\tint x = idx % Width;\n\t\t\t\t\tint y = idx / Width;\n\t\t\t\t\tif ( InBounds( x, y ) \u0026\u0026 _types[x, y] == level.ObjectiveType )\n\t\t\t\t\t\tadd\u002B\u002B;\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\tcase ColourBreakObjectiveKind.MakeSpecials:\n\t\t\t\tadd = rewardKind == SpecialKind.None ? 0 : 1;\n\t\t\t\tbreak;\n\t\t\tcase ColourBreakObjectiveKind.TriggerSpecials:\n\t\t\t\tadd = triggeredSpecials;\n\t\t\t\tbreak;\n\t\t\tcase ColourBreakObjectiveKind.ChainCombos:\n\t\t\t\tadd = _comboCount \u003E 1 ? 1 : 0;\n\t\t\t\tbreak;\n\t\t}\n\n\t\tif ( add \u003E 0 )\n\t\t\t_objectiveProgress = Math.Min( level.ObjectiveTarget, _objectiveProgress \u002B add );\n\t}\n\n\tvoid ExpandSpecialClears( HashSet\u003Cint\u003E cells )\n\t{\n\t\tbool changed;\n\t\tint guard = 0;\n\t\tdo\n\t\t{\n\t\t\tchanged = false;\n\t\t\tvar snapshot = new List\u003Cint\u003E( cells );\n\t\t\tforeach ( var idx in snapshot )\n\t\t\t{\n\t\t\t\tint before = cells.Count;\n\t\t\t\tAddSpecialCells( idx % Width, idx / Width, cells );\n\t\t\t\tif ( cells.Count \u003E before ) changed = true;\n\t\t\t}\n\t\t}\n\t\twhile ( changed \u0026\u0026 \u002B\u002Bguard \u003C Width * Height );\n\t}\n\n\tvoid AddSpecialCells( int x, int y, HashSet\u003Cint\u003E cells )\n\t{\n\t\tif ( !InBounds( x, y ) ) return;\n\t\tswitch ( _specials[x, y] )\n\t\t{\n\t\t\tcase SpecialKind.RowBlast:\n\t\t\t\tfor ( int cx = 0; cx \u003C Width; cx\u002B\u002B ) cells.Add( y * Width \u002B cx );\n\t\t\t\tbreak;\n\t\t\tcase SpecialKind.ColumnBlast:\n\t\t\t\tfor ( int cy = 0; cy \u003C Height; cy\u002B\u002B ) cells.Add( cy * Width \u002B x );\n\t\t\t\tbreak;\n\t\t\tcase SpecialKind.Bomb:\n\t\t\t\tfor ( int cy = y - 2; cy \u003C= y \u002B 2; cy\u002B\u002B )\n\t\t\t\t\tfor ( int cx = x - 2; cx \u003C= x \u002B 2; cx\u002B\u002B )\n\t\t\t\t\t\tif ( InBounds( cx, cy ) ) cells.Add( cy * Width \u002B cx );\n\t\t\t\tbreak;\n\t\t}\n\t}\n\n\tvoid TryChooseSpecialReward( HashSet\u003Cint\u003E matches, out int rewardIdx, out SpecialKind kind )\n\t{\n\t\trewardIdx = -1;\n\t\tkind = SpecialKind.None;\n\t\tif ( matches.Count \u003C 4 ) return;\n\n\t\tint preferred = matches.Contains( _swapBX \u002B _swapBY * Width ) ? _swapBX \u002B _swapBY * Width :\n\t\t\tmatches.Contains( _swapAX \u002B _swapAY * Width ) ? _swapAX \u002B _swapAY * Width :\n\t\t\tmatches.First();\n\n\t\trewardIdx = preferred;\n\t\tkind = matches.Count \u003E= 5 ? SpecialKind.Bomb : SpecialKind.RowBlast;\n\n\t\tint x = preferred % Width;\n\t\tint y = preferred / Width;\n\t\tint sameRow = 0;\n\t\tint sameColumn = 0;\n\t\tforeach ( var idx in matches )\n\t\t{\n\t\t\tif ( idx / Width == y ) sameRow\u002B\u002B;\n\t\t\tif ( idx % Width == x ) sameColumn\u002B\u002B;\n\t\t}\n\t\tif ( matches.Count \u003C 5 )\n\t\t\tkind = sameColumn \u003E sameRow ? SpecialKind.ColumnBlast : SpecialKind.RowBlast;\n\t}\n\n\tvoid SetSpecialAt( int x, int y, SpecialKind kind )\n\t{\n\t\tif ( !InBounds( x, y ) ) return;\n\t\t_specials[x, y] = kind;\n\t\tvar v = _visuals[x, y];\n\t\tif ( v == null ) return;\n\t\tv.Special = kind;\n\t\tUpdateSpecialVisual( v );\n\t}\n\n\tvoid UpdateSpecialVisual( CandyVisual v )\n\t{\n\t\tif ( v?.SpecialBadgeRenderer == null ) return;\n\t\tv.SpecialBadgeRenderer.Tint = v.Special switch\n\t\t{\n\t\t\tSpecialKind.RowBlast =\u003E new Color( 1f, 0.86f, 0.12f, 1f ),\n\t\t\tSpecialKind.ColumnBlast =\u003E new Color( 0.22f, 0.92f, 1f, 1f ),\n\t\t\tSpecialKind.Bomb =\u003E new Color( 1f, 0.20f, 0.06f, 1f ),\n\t\t\t_ =\u003E new Color( 1f, 1f, 1f, 0f )\n\t\t};\n\t\tv.SpecialBadge.LocalRotation = v.Special switch\n\t\t{\n\t\t\tSpecialKind.ColumnBlast =\u003E Rotation.FromYaw( 90f ),\n\t\t\tSpecialKind.Bomb =\u003E Rotation.FromYaw( 45f ),\n\t\t\t_ =\u003E Rotation.Identity\n\t\t};\n\t\tv.SpecialBadge.LocalScale = v.Special == SpecialKind.Bomb\n\t\t\t? new Vector3( 0.22f, 0.04f, 0.22f )\n\t\t\t: v.Special == SpecialKind.None\n\t\t\t\t? Vector3.Zero\n\t\t\t\t: new Vector3( 0.44f, 0.035f, 0.06f );\n\t}\n\n\tvoid SpawnBurstAt( Vector3 pos, Color color )\n\t{\n\t\tif ( !EffectsEnabled ) return;\n\t\tint count = 24;\n\t\tfor ( int i = 0; i \u003C count; i\u002B\u002B )\n\t\t{\n\t\t\tvar go = RentBurstObject( \u0022Colour Spark\u0022 );\n\t\t\tgo.WorldPosition = pos \u002B new Vector3( Game.Random.Float( -4f, 4f ), Game.Random.Float( -3f, 3f ), Game.Random.Float( -4f, 4f ) );\n\t\t\tgo.WorldRotation = Rotation.Random;\n\t\t\tbool hot = i % 3 != 0;\n\t\t\tfloat scale = hot ? Game.Random.Float( 0.09f, 0.18f ) : Game.Random.Float( 0.045f, 0.10f );\n\t\t\tgo.WorldScale = hot ? new Vector3( scale * 0.75f, scale * 0.22f, scale * 1.9f ) : Vector3.One * scale;\n\t\t\tvar mr = go.GetComponent\u003CModelRenderer\u003E();\n\t\t\tmr.Model = hot ? (_boxModel ?? _sphereModel) : ((i % 2 == 0 \u0026\u0026 _sphereModel != null) ? _sphereModel : _boxModel);\n\t\t\tvar fireTint = i % 4 == 0 ? new Color( 1f, 0.18f, 0.02f ) : new Color( 1f, 0.70f, 0.10f );\n\t\t\tmr.Tint = hot ? Color.Lerp( fireTint, color, 0.28f ) : Color.Lerp( color, Color.White, 0.45f );\n\n\t\t\tfloat ang = (i / (float)count) * MathF.PI * 2f \u002B Game.Random.Float( -0.4f, 0.4f );\n\t\t\tfloat speed = hot ? Game.Random.Float( 180f, 420f ) : Game.Random.Float( 320f, 620f );\n\t\t\tvar vel = new Vector3( MathF.Cos( ang ) * speed, Game.Random.Float( -180f, -30f ), Game.Random.Float( 260f, 650f ) \u002B MathF.Sin( ang ) * speed * 0.25f );\n\n\t\t\t_bursts.Add( new Burst\n\t\t\t{\n\t\t\t\tGo = go,\n\t\t\t\tRenderer = mr,\n\t\t\t\tVelocity = vel,\n\t\t\t\tLife = hot ? 0.55f : 0.82f,\n\t\t\t\tMaxLife = hot ? 0.55f : 0.82f,\n\t\t\t\tBaseTint = mr.Tint,\n\t\t\t\tStartScale = scale,\n\t\t\t} );\n\t\t}\n\t}\n\n\tvoid SpawnFireColumn( Vector3 pos, float intensity )\n\t{\n\t\tif ( !EffectsEnabled ) return;\n\t\tint count = (int)(18 * intensity);\n\t\tfor ( int i = 0; i \u003C count; i\u002B\u002B )\n\t\t{\n\t\t\tvar go = RentBurstObject( \u0022Match Fire\u0022 );\n\t\t\tgo.WorldPosition = pos \u002B new Vector3( Game.Random.Float( -18f, 18f ), Game.Random.Float( -8f, 4f ), Game.Random.Float( -8f, 8f ) );\n\t\t\tgo.WorldRotation = Rotation.Random;\n\t\t\tfloat scale = Game.Random.Float( 0.12f, 0.28f ) * intensity;\n\t\t\tgo.WorldScale = new Vector3( scale * 0.75f, scale * 0.16f, scale * Game.Random.Float( 2.2f, 3.8f ) );\n\t\t\tvar mr = go.GetComponent\u003CModelRenderer\u003E();\n\t\t\tmr.Model = _boxModel ?? _sphereModel;\n\t\t\tmr.Tint = i % 3 == 0 ? new Color( 1f, 0.95f, 0.35f, 0.95f ) : new Color( 1f, 0.28f, 0.03f, 0.85f );\n\n\t\t\t_bursts.Add( new Burst\n\t\t\t{\n\t\t\t\tGo = go,\n\t\t\t\tRenderer = mr,\n\t\t\t\tVelocity = new Vector3( Game.Random.Float( -80f, 80f ), Game.Random.Float( -60f, 10f ), Game.Random.Float( 520f, 920f ) * intensity ),\n\t\t\t\tLife = Game.Random.Float( 0.42f, 0.72f ),\n\t\t\t\tMaxLife = 0.72f,\n\t\t\t\tBaseTint = mr.Tint,\n\t\t\t\tStartScale = scale,\n\t\t\t} );\n\t\t}\n\n\t\tvar lightGo = new GameObject( true, \u0022Match Fire Light\u0022 );\n\t\tlightGo.Flags = GameObjectFlags.NotNetworked;\n\t\tlightGo.WorldPosition = pos \u002B new Vector3( 0f, -18f, 22f );\n\t\tvar light = lightGo.AddComponent\u003CPointLight\u003E();\n\t\tlight.LightColor = new Color( 1f, 0.42f, 0.08f );\n\t\tlight.Radius = 360f * intensity;\n\t\t_bursts.Add( new Burst\n\t\t{\n\t\t\tGo = lightGo,\n\t\t\tRenderer = null,\n\t\t\tVelocity = Vector3.Zero,\n\t\t\tLife = 0.34f,\n\t\t\tMaxLife = 0.34f,\n\t\t\tBaseTint = Color.White,\n\t\t\tStartScale = 1f,\n\t\t} );\n\t}\n\n\tvoid AnimateBursts()\n\t{\n\t\tfloat dt = Time.Delta;\n\t\tfor ( int i = _bursts.Count - 1; i \u003E= 0; i-- )\n\t\t{\n\t\t\tvar b = _bursts[i];\n\t\t\tb.Life -= dt;\n\t\t\tif ( b.Life \u003C= 0f || b.Go == null )\n\t\t\t{\n\t\t\t\t// Renderer bursts go back to the pool; the lone PointLight burst is destroyed.\n\t\t\t\tif ( b.Go != null \u0026\u0026 b.Renderer != null )\n\t\t\t\t\tReturnBurstObject( b.Go );\n\t\t\t\telse\n\t\t\t\t\tb.Go?.Destroy();\n\t\t\t\t_bursts.RemoveAt( i );\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\t// gravity \u002B drag\n\t\t\tb.Velocity.z -= 1400f * dt;\n\t\t\tb.Velocity *= 1f - dt * 1.4f;\n\t\t\tb.Go.WorldPosition \u002B= b.Velocity * dt;\n\t\t\tb.Go.WorldRotation *= Rotation.From( new Angles( dt * 540f, dt * 720f, dt * 360f ) );\n\n\t\t\tfloat k = b.Life / b.MaxLife;\n\t\t\tif ( b.Renderer != null )\n\t\t\t{\n\t\t\t\tb.Go.WorldScale *= 1f \u002B dt * 0.55f;\n\t\t\t\tvar t = b.BaseTint;\n\t\t\t\tt.a = k;\n\t\t\t\tb.Renderer.Tint = t;\n\t\t\t}\n\t\t}\n\t}\n\n\tvoid SpawnShockwave( Vector3 pos, Color color, float life, float radius )\n\t{\n\t\tif ( !EffectsEnabled ) return;\n\t\tvar go = new GameObject( true, \u0022ColourBreak Shockwave\u0022 );\n\t\tgo.Flags = GameObjectFlags.NotNetworked;\n\t\tgo.WorldPosition = pos \u002B new Vector3( 0f, -3f, 0f );\n\t\tgo.WorldScale = new Vector3( 0.08f, 0.01f, 0.08f );\n\t\tvar mr = go.AddComponent\u003CModelRenderer\u003E();\n\t\tmr.Model = _sphereModel ?? _boxModel;\n\t\tmr.Tint = new Color( color.r, color.g, color.b, 0.55f );\n\t\t_shockwaves.Add( new Shockwave\n\t\t{\n\t\t\tGo = go,\n\t\t\tRenderer = mr,\n\t\t\tTint = mr.Tint,\n\t\t\tLife = life,\n\t\t\tMaxLife = life,\n\t\t\tRadius = radius,\n\t\t} );\n\t}\n\n\tvoid AnimateShockwaves()\n\t{\n\t\tfloat dt = Time.Delta;\n\t\tfor ( int i = _shockwaves.Count - 1; i \u003E= 0; i-- )\n\t\t{\n\t\t\tvar wave = _shockwaves[i];\n\t\t\twave.Life -= dt;\n\t\t\tif ( wave.Life \u003C= 0f || wave.Go == null )\n\t\t\t{\n\t\t\t\twave.Go?.Destroy();\n\t\t\t\t_shockwaves.RemoveAt( i );\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tfloat k = 1f - wave.Life / wave.MaxLife;\n\t\t\tfloat eased = EaseOutCubic( k );\n\t\t\tfloat scale = MathX.Lerp( 0.04f, wave.Radius / 50f, eased );\n\t\t\twave.Go.WorldScale = new Vector3( scale, 0.012f, scale );\n\t\t\tvar tint = wave.Tint;\n\t\t\ttint.a = 0.55f * (1f - k);\n\t\t\twave.Renderer.Tint = tint;\n\t\t}\n\t}\n\n\tbool AllClearAnimsDone()\n\t{\n\t\tfor ( int y = 0; y \u003C Height; y\u002B\u002B )\n\t\t\tfor ( int x = 0; x \u003C Width; x\u002B\u002B )\n\t\t\t{\n\t\t\t\tvar v = _visuals[x, y];\n\t\t\t\tif ( v != null \u0026\u0026 v.Clearing \u0026\u0026 v.ClearTimer \u003E 0f ) return false;\n\t\t\t}\n\t\treturn true;\n\t}\n\n\tvoid DestroyClearedCandies()\n\t{\n\t\tfor ( int y = 0; y \u003C Height; y\u002B\u002B )\n\t\t\tfor ( int x = 0; x \u003C Width; x\u002B\u002B )\n\t\t\t{\n\t\t\t\tvar v = _visuals[x, y];\n\t\t\t\tif ( v != null \u0026\u0026 v.Clearing )\n\t\t\t\t{\n\t\t\t\t\tv.Go?.Destroy();\n\t\t\t\t\t_visuals[x, y] = null;\n\t\t\t\t\t_types[x, y] = Empty;\n\t\t\t\t}\n\t\t\t}\n\t}\n\n\tbool AllAtAnchor()\n\t{\n\t\tfor ( int y = 0; y \u003C Height; y\u002B\u002B )\n\t\t\tfor ( int x = 0; x \u003C Width; x\u002B\u002B )\n\t\t\t{\n\t\t\t\tvar v = _visuals[x, y];\n\t\t\t\tif ( v == null ) continue;\n\t\t\t\tif ( v.Spawning ) return false;\n\t\t\t\tif ( (v.Go.WorldPosition - v.Anchor).LengthSquared \u003E 4f ) return false;\n\t\t\t}\n\t\treturn true;\n\t}\n\n\tvoid CollapseColumns()\n\t{\n\t\tfor ( int x = 0; x \u003C Width; x\u002B\u002B )\n\t\t{\n\t\t\tint writeY = 0;\n\t\t\tfor ( int y = 0; y \u003C Height; y\u002B\u002B )\n\t\t\t{\n\t\t\t\tif ( _types[x, y] == Empty ) continue;\n\t\t\t\tif ( y != writeY )\n\t\t\t\t{\n\t\t\t\t\t_types[x, writeY] = _types[x, y];\n\t\t\t\t\t_types[x, y] = Empty;\n\t\t\t\t\t_specials[x, writeY] = _specials[x, y];\n\t\t\t\t\t_specials[x, y] = SpecialKind.None;\n\t\t\t\t\t_visuals[x, writeY] = _visuals[x, y];\n\t\t\t\t\t_visuals[x, y] = null;\n\t\t\t\t\tvar v = _visuals[x, writeY];\n\t\t\t\t\tif ( v != null )\n\t\t\t\t\t{\n\t\t\t\t\t\tv.Anchor = CellToWorld( x, writeY );\n\t\t\t\t\t\tv.Special = _specials[x, writeY];\n\t\t\t\t\t\tUpdateSpecialVisual( v );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\twriteY\u002B\u002B;\n\t\t\t}\n\t\t}\n\t}\n\n\tvoid Refill()\n\t{\n\t\tfor ( int x = 0; x \u003C Width; x\u002B\u002B )\n\t\t{\n\t\t\tint spawnIndex = 0;\n\t\t\tfor ( int y = 0; y \u003C Height; y\u002B\u002B )\n\t\t\t{\n\t\t\t\tif ( _types[x, y] != Empty ) continue;\n\t\t\t\tint type = Game.Random.Int( 0, CandyTypeCount - 1 );\n\t\t\t\t_specials[x, y] = SpecialKind.None;\n\t\t\t\tSpawnCandy( x, y, type, instant: false );\n\t\t\t\t// Stagger spawn position so they form a falling stream\n\t\t\t\tvar v = _visuals[x, y];\n\t\t\t\tif ( v != null )\n\t\t\t\t{\n\t\t\t\t\tvar p = v.Go.WorldPosition;\n\t\t\t\t\tp.z \u002B= spawnIndex * CellSpacing * 0.6f;\n\t\t\t\t\tv.Go.WorldPosition = p;\n\t\t\t\t}\n\t\t\t\tspawnIndex\u002B\u002B;\n\t\t\t}\n\t\t}\n\t}\n\n\tHashSet\u003Cint\u003E FindMatches()\n\t{\n\t\tvar result = new HashSet\u003Cint\u003E();\n\t\tfor ( int y = 0; y \u003C Height; y\u002B\u002B )\n\t\t{\n\t\t\tint runStart = 0;\n\t\t\tfor ( int x = 1; x \u003C= Width; x\u002B\u002B )\n\t\t\t{\n\t\t\t\tbool atEnd = x == Width;\n\t\t\t\tif ( !atEnd \u0026\u0026 _types[x, y] == _types[runStart, y] \u0026\u0026 _types[x, y] != Empty ) continue;\n\t\t\t\tint runLen = x - runStart;\n\t\t\t\tif ( _types[runStart, y] != Empty \u0026\u0026 runLen \u003E= 3 )\n\t\t\t\t\tfor ( int rx = runStart; rx \u003C x; rx\u002B\u002B ) result.Add( y * Width \u002B rx );\n\t\t\t\trunStart = x;\n\t\t\t}\n\t\t}\n\t\tfor ( int x = 0; x \u003C Width; x\u002B\u002B )\n\t\t{\n\t\t\tint runStart = 0;\n\t\t\tfor ( int y = 1; y \u003C= Height; y\u002B\u002B )\n\t\t\t{\n\t\t\t\tbool atEnd = y == Height;\n\t\t\t\tif ( !atEnd \u0026\u0026 _types[x, y] == _types[x, runStart] \u0026\u0026 _types[x, y] != Empty ) continue;\n\t\t\t\tint runLen = y - runStart;\n\t\t\t\tif ( _types[x, runStart] != Empty \u0026\u0026 runLen \u003E= 3 )\n\t\t\t\t\tfor ( int ry = runStart; ry \u003C y; ry\u002B\u002B ) result.Add( ry * Width \u002B x );\n\t\t\t\trunStart = y;\n\t\t\t}\n\t\t}\n\t\treturn result;\n\t}\n\n\tbool HasPossibleMove()\n\t{\n\t\tif ( _types == null ) return false;\n\t\tfor ( int y = 0; y \u003C Height; y\u002B\u002B )\n\t\t{\n\t\t\tfor ( int x = 0; x \u003C Width; x\u002B\u002B )\n\t\t\t{\n\t\t\t\tif ( _specials != null \u0026\u0026 _specials[x, y] != SpecialKind.None )\n\t\t\t\t\treturn true;\n\t\t\t\tif ( x \u002B 1 \u003C Width \u0026\u0026 SwapWouldMatch( x, y, x \u002B 1, y ) ) return true;\n\t\t\t\tif ( y \u002B 1 \u003C Height \u0026\u0026 SwapWouldMatch( x, y, x, y \u002B 1 ) ) return true;\n\t\t\t}\n\t\t}\n\t\treturn false;\n\t}\n\n\tbool SwapWouldMatch( int x1, int y1, int x2, int y2 )\n\t{\n\t\t(_types[x1, y1], _types[x2, y2]) = (_types[x2, y2], _types[x1, y1]);\n\t\tbool result = IsMatchAt( x1, y1 ) || IsMatchAt( x2, y2 );\n\t\t(_types[x1, y1], _types[x2, y2]) = (_types[x2, y2], _types[x1, y1]);\n\t\treturn result;\n\t}\n\n\tbool IsMatchAt( int x, int y )\n\t{\n\t\tint type = _types[x, y];\n\t\tif ( type == Empty ) return false;\n\n\t\tint count = 1;\n\t\tfor ( int cx = x - 1; cx \u003E= 0 \u0026\u0026 _types[cx, y] == type; cx-- ) count\u002B\u002B;\n\t\tfor ( int cx = x \u002B 1; cx \u003C Width \u0026\u0026 _types[cx, y] == type; cx\u002B\u002B ) count\u002B\u002B;\n\t\tif ( count \u003E= 3 ) return true;\n\n\t\tcount = 1;\n\t\tfor ( int cy = y - 1; cy \u003E= 0 \u0026\u0026 _types[x, cy] == type; cy-- ) count\u002B\u002B;\n\t\tfor ( int cy = y \u002B 1; cy \u003C Height \u0026\u0026 _types[x, cy] == type; cy\u002B\u002B ) count\u002B\u002B;\n\t\treturn count \u003E= 3;\n\t}\n\n\tvoid ReshuffleBoardForAvailableMove()\n\t{\n\t\tvar types = new List\u003Cint\u003E( Width * Height );\n\t\tfor ( int y = 0; y \u003C Height; y\u002B\u002B )\n\t\t\tfor ( int x = 0; x \u003C Width; x\u002B\u002B )\n\t\t\t\tif ( _types[x, y] != Empty ) types.Add( _types[x, y] );\n\n\t\tfor ( int attempt = 0; attempt \u003C 40; attempt\u002B\u002B )\n\t\t{\n\t\t\tShuffleList( types );\n\t\t\tint i = 0;\n\t\t\tfor ( int y = 0; y \u003C Height; y\u002B\u002B )\n\t\t\t{\n\t\t\t\tfor ( int x = 0; x \u003C Width; x\u002B\u002B )\n\t\t\t\t{\n\t\t\t\t\t_types[x, y] = types[i\u002B\u002B % types.Count];\n\t\t\t\t\t_specials[x, y] = SpecialKind.None;\n\t\t\t\t}\n\t\t\t}\n\t\t\tif ( FindMatches().Count == 0 \u0026\u0026 HasPossibleMove() )\n\t\t\t\tbreak;\n\t\t}\n\n\t\tfor ( int y = 0; y \u003C Height; y\u002B\u002B )\n\t\t{\n\t\t\tfor ( int x = 0; x \u003C Width; x\u002B\u002B )\n\t\t\t{\n\t\t\t\tvar v = _visuals[x, y];\n\t\t\t\tif ( v == null ) continue;\n\t\t\t\tv.Type = _types[x, y];\n\t\t\t\tv.Special = SpecialKind.None;\n\t\t\t\tv.Renderer.Model = ModelForType( v.Type );\n\t\t\t\tApplyPieceVisualStyle( v );\n\t\t\t\tUpdateSpecialVisual( v );\n\t\t\t}\n\t\t}\n\n\t\tSpawnShockwave( BoardOrigin, new Color( 0.25f, 0.92f, 1f ), 0.7f, 150f );\n\t\tPunchCamera( 2f, 1.2f );\n\t\tLog.Info( \u0022Board reshuffled: no available moves.\u0022 );\n\t}\n\n\tvoid EndEndlessRun()\n\t{\n\t\tCurrentState = GameState.Lost;\n\t\tEndlessRecordSet = ColourBreakProgressStore.RecordEndlessScore( _saveData, _score );\n\n\t\ttry\n\t\t{\n\t\t\tSandbox.Services.Stats.Increment( \u0022endless-runs\u0022, 1 );\n\t\t\tSandbox.Services.Stats.SetValue( \u0022endless-best\u0022, EndlessBest, \u0022\u0022, null );\n\t\t}\n\t\tcatch ( Exception e )\n\t\t{\n\t\t\tLog.Info( $\u0022Leaderboard stats unavailable: {e.Message}\u0022 );\n\t\t}\n\n\t\tPlayUiSound( DeniedSound, 0.85f, 0.72f );\n\t\tSpawnShockwave( BoardOrigin, new Color( 1f, 0.18f, 0.06f ), 0.7f, 150f );\n\t\tPunchCamera( 3f, 2.4f );\n\t}\n\n\tvoid CheckLevelEnd()\n\t{\n\t\tif ( CurrentState != GameState.Playing ) return;\n\t\tif ( IsEndless ) return;   // endless ends only on a dead board\n\t\tif ( _score \u003E= TargetScore \u0026\u0026 ObjectiveComplete )\n\t\t{\n\t\t\tCurrentState = GameState.Won;\n\t\t\tSaveWinProgress();\n\t\t\tPlayUiSound( ComboSound, 1f, 1.18f );\n\t\t\tSpawnFireColumn( BoardOrigin, 1.4f );\n\t\t\tSpawnShockwave( BoardOrigin, new Color( 1f, 0.86f, 0.12f ), 0.85f, 190f );\n\t\t\tPunchCamera( 5f, 3.2f );\n\t\t\treturn;\n\t\t}\n\t\tif ( _moves \u003E= MoveLimit )\n\t\t{\n\t\t\tCurrentState = GameState.Lost;\n\t\t\tPlayUiSound( DeniedSound, 0.85f, 0.72f );\n\t\t\tSpawnShockwave( BoardOrigin, new Color( 1f, 0.18f, 0.06f ), 0.7f, 130f );\n\t\t\tPunchCamera( 2.5f, 2.0f );\n\t\t}\n\t}\n\n\tvoid ShuffleList( List\u003Cint\u003E list )\n\t{\n\t\tfor ( int i = list.Count - 1; i \u003E 0; i-- )\n\t\t{\n\t\t\tint j = Game.Random.Int( 0, i );\n\t\t\t(list[i], list[j]) = (list[j], list[i]);\n\t\t}\n\t}\n\n\tint CountSpecials()\n\t{\n\t\tif ( _specials == null ) return 0;\n\t\tint count = 0;\n\t\tfor ( int y = 0; y \u003C Height; y\u002B\u002B )\n\t\t\tfor ( int x = 0; x \u003C Width; x\u002B\u002B )\n\t\t\t\tif ( _specials[x, y] != SpecialKind.None ) count\u002B\u002B;\n\t\treturn count;\n\t}\n\n\t// -------------------- visuals --------------------\n\n\tvoid AnimateCandies()\n\t{\n\t\tif ( _visuals == null ) return;\n\t\tfloat dt = Time.Delta;\n\n\t\tfor ( int y = 0; y \u003C Height; y\u002B\u002B )\n\t\t{\n\t\t\tfor ( int x = 0; x \u003C Width; x\u002B\u002B )\n\t\t\t{\n\t\t\t\tvar v = _visuals[x, y];\n\t\t\t\tif ( v == null || v.Go == null ) continue;\n\n\t\t\t\tint t = v.Type;\n\t\t\t\tvar baseShape = PieceShape( t );\n\t\t\t\tfloat baseScale = CandyScale;\n\n\t\t\t\t// 1) Clearing animation: shrink \u002B spin fast\n\t\t\t\tif ( v.Clearing )\n\t\t\t\t{\n\t\t\t\t\tv.ClearTimer -= dt;\n\t\t\t\t\tfloat k = MathF.Max( 0f, v.ClearTimer / ClearDuration );\n\t\t\t\t\tfloat s = baseScale * EaseOutBack( k ) * 1.4f * k;\n\t\t\t\t\tv.Go.WorldScale = baseShape * s;\n\t\t\t\t\tv.Go.WorldRotation *= Rotation.FromYaw( dt * 720f );\n\t\t\t\t\tv.Renderer.Tint = Color.Lerp( PieceColor( t ), Color.White, 1f - k );\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\n\t\t\t\t// 2) Swap tween\n\t\t\t\tif ( v.Swapping )\n\t\t\t\t{\n\t\t\t\t\tv.SwapT \u002B= dt / SwapDuration;\n\t\t\t\t\tfloat k = MathF.Min( 1f, v.SwapT );\n\t\t\t\t\tfloat e = EaseInOutCubic( k );\n\t\t\t\t\tvar pos = Vector3.Lerp( v.SwapFrom, v.SwapTo, e );\n\t\t\t\t\t// Lift slightly off the board for an arc\n\t\t\t\t\tpos.y -= MathF.Sin( k * MathF.PI ) * CellSpacing * 0.18f;\n\t\t\t\t\tv.Go.WorldPosition = pos;\n\t\t\t\t\tif ( k \u003E= 1f ) { v.Swapping = false; v.Go.WorldPosition = v.SwapTo; v.Anchor = v.SwapTo; }\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\t// 3) Falling toward anchor (used for collapse \u002B refill)\n\t\t\t\t\tvar pos = v.Go.WorldPosition;\n\t\t\t\t\tvar to = v.Anchor;\n\t\t\t\t\tvar diff = to - pos;\n\t\t\t\t\tif ( diff.LengthSquared \u003E 1f )\n\t\t\t\t\t{\n\t\t\t\t\t\t// gravity-ish acceleration toward anchor on Z (vertical)\n\t\t\t\t\t\tv.Velocity.z -= 4500f * dt;\n\t\t\t\t\t\tpos.z \u002B= v.Velocity.z * dt;\n\t\t\t\t\t\tpos.x = MathX.Lerp( pos.x, to.x, dt * 14f );\n\t\t\t\t\t\tpos.y = MathX.Lerp( pos.y, to.y, dt * 14f );\n\n\t\t\t\t\t\tif ( pos.z \u003C= to.z )\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tpos.z = to.z;\n\t\t\t\t\t\t\t// Squash on landing\n\t\t\t\t\t\t\tv.Velocity.z = 0f;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tv.Go.WorldPosition = pos;\n\t\t\t\t\t}\n\t\t\t\t\telse\n\t\t\t\t\t{\n\t\t\t\t\t\tv.Go.WorldPosition = to;\n\t\t\t\t\t\tv.Velocity = Vector3.Zero;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\t// 4) Spawn pop-in\n\t\t\t\tfloat spawnScale = 1f;\n\t\t\t\tif ( v.Spawning )\n\t\t\t\t{\n\t\t\t\t\tv.SpawnTimer -= dt;\n\t\t\t\t\tfloat k = MathF.Max( 0f, v.SpawnTimer / 0.25f );\n\t\t\t\t\tspawnScale = MathX.Lerp( 1f, 0.4f, k );\n\t\t\t\t\tif ( v.SpawnTimer \u003C= 0f ) v.Spawning = false;\n\t\t\t\t}\n\n\t\t\t\t// 5) Idle bob \u002B gentle spin\n\t\t\t\tv.BobPhase \u002B= dt;\n\t\t\t\tfloat bob = MathF.Sin( v.BobPhase * 2.4f ) * 1.2f;\n\t\t\t\tif ( !v.Swapping \u0026\u0026 (v.Go.WorldPosition - v.Anchor).LengthSquared \u003C 4f )\n\t\t\t\t{\n\t\t\t\t\tvar p = v.Anchor;\n\t\t\t\t\tp.y -= bob;\n\t\t\t\t\tv.Go.WorldPosition = p;\n\t\t\t\t}\n\t\t\t\tv.Go.WorldRotation *= Rotation.FromYaw( dt * (10f \u002B (t * 3f)) );\n\n\t\t\t\t// 6) Final scale (with highlight applied later in ApplyHighlights)\n\t\t\t\tv.Go.WorldScale = baseShape * baseScale * spawnScale;\n\t\t\t}\n\t\t}\n\t}\n\n\tvoid ApplyHighlights()\n\t{\n\t\tif ( _visuals == null ) return;\n\t\tfor ( int y = 0; y \u003C Height; y\u002B\u002B )\n\t\t{\n\t\t\tfor ( int x = 0; x \u003C Width; x\u002B\u002B )\n\t\t\t{\n\t\t\t\tvar v = _visuals[x, y];\n\t\t\t\tif ( v == null || v.Renderer == null || v.Clearing ) continue;\n\n\t\t\t\tvar baseTint = PieceColor( v.Type );\n\t\t\t\tbool isCursor = x == _cursorX \u0026\u0026 y == _cursorY;\n\t\t\t\tbool isSelected = _hasSelection \u0026\u0026 x == _selectedX \u0026\u0026 y == _selectedY;\n\t\t\t\tbool isLegalNeighbour = _hasSelection \u0026\u0026 !isSelected \u0026\u0026 AreAdjacent( _selectedX, _selectedY, x, y );\n\t\t\t\tbool isHint = _hasHint \u0026\u0026 ((x == _hintAX \u0026\u0026 y == _hintAY) || (x == _hintBX \u0026\u0026 y == _hintBY));\n\n\t\t\t\tfloat scaleMul = 1f;\n\t\t\t\tif ( isHint \u0026\u0026 !isCursor \u0026\u0026 !isSelected )\n\t\t\t\t{\n\t\t\t\t\tfloat p = 0.5f \u002B 0.5f * MathF.Sin( Time.Now * 7f );\n\t\t\t\t\tbaseTint = Color.Lerp( baseTint, Color.White, 0.30f \u002B 0.45f * p );\n\t\t\t\t\tscaleMul \u002B= 0.18f \u002B 0.16f * p;\n\t\t\t\t}\n\t\t\t\tif ( isCursor )\n\t\t\t\t{\n\t\t\t\t\tfloat p = 0.5f \u002B 0.5f * MathF.Sin( Time.Now * 12f );\n\t\t\t\t\t// Instead of a box, pulse the candy itself significantly brighter and bigger\n\t\t\t\t\tbaseTint = Color.Lerp( baseTint, Color.White, 0.40f \u002B 0.40f * p );\n\t\t\t\t\tscaleMul \u002B= 0.25f \u002B 0.15f * p;\n\t\t\t\t}\n\t\t\t\tif ( isSelected )\n\t\t\t\t{\n\t\t\t\t\t// Selection gets a distinct yellow overlay\n\t\t\t\t\tbaseTint = Color.Lerp( baseTint, new Color( 1f, 0.95f, 0.2f ), 0.60f );\n\t\t\t\t\tscaleMul \u002B= 0.35f;\n\t\t\t\t}\n\t\t\t\tif ( isLegalNeighbour )\n\t\t\t\t{\n\t\t\t\t\tfloat p = 0.5f \u002B 0.5f * MathF.Sin( Time.Now * 9f );\n\t\t\t\t\tbaseTint = Color.Lerp( baseTint, new Color( 0.22f, 0.92f, 1f ), 0.18f \u002B 0.14f * p );\n\t\t\t\t\tscaleMul \u002B= 0.08f \u002B 0.05f * p;\n\t\t\t\t}\n\n\t\t\t\tv.Renderer.Tint = baseTint;\n\t\t\t\tif ( v.RimRenderer != null )\n\t\t\t\t\tv.RimRenderer.Tint = Color.Lerp( baseTint, Color.Black, isSelected ? 0.12f : isLegalNeighbour ? 0.22f : 0.36f );\n\t\t\t\tif ( v.FaceRenderer != null )\n\t\t\t\t\tv.FaceRenderer.Tint = Color.Lerp( baseTint, Color.White, isCursor || isSelected || isLegalNeighbour ? 0.45f : 0.20f );\n\t\t\t\tif ( v.AccentRenderer != null )\n\t\t\t\t\tv.AccentRenderer.Tint = Color.Lerp( baseTint, Color.White, isCursor || isSelected || isLegalNeighbour ? 0.82f : 0.52f );\n\t\t\t\tif ( v.ShineRenderer != null )\n\t\t\t\t\tv.ShineRenderer.Tint = isCursor || isSelected || isLegalNeighbour ? new Color( 1f, 1f, 1f, 1f ) : new Color( 1f, 1f, 1f, 0.74f );\n\t\t\t\tif ( v.Halo != null )\n\t\t\t\t{\n\t\t\t\t\tfloat p = 0.5f \u002B 0.5f * MathF.Sin( Time.Now * 10f );\n\t\t\t\t\tif ( isSelected )\n\t\t\t\t\t{\n\t\t\t\t\t\tv.Halo.LocalScale = new Vector3( 1.34f \u002B 0.05f * p, 0.055f, 1.34f \u002B 0.05f * p );\n\t\t\t\t\t\tif ( v.HaloRenderer != null ) v.HaloRenderer.Tint = new Color( 1f, 0.86f, 0.08f, 0.90f );\n\t\t\t\t\t}\n\t\t\t\t\telse if ( isCursor )\n\t\t\t\t\t{\n\t\t\t\t\t\tv.Halo.LocalScale = new Vector3( 1.20f \u002B 0.05f * p, 0.040f, 1.20f \u002B 0.05f * p );\n\t\t\t\t\t\tif ( v.HaloRenderer != null ) v.HaloRenderer.Tint = new Color( 1f, 1f, 1f, 0.68f );\n\t\t\t\t\t}\n\t\t\t\t\telse\n\t\t\t\t\t{\n\t\t\t\t\t\tv.Halo.LocalScale = Vector3.Zero;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tif ( v.Guide != null )\n\t\t\t\t{\n\t\t\t\t\tfloat p = 0.5f \u002B 0.5f * MathF.Sin( Time.Now * 8f );\n\t\t\t\t\tif ( isLegalNeighbour )\n\t\t\t\t\t{\n\t\t\t\t\t\tv.Guide.LocalScale = new Vector3( 1.16f \u002B 0.07f * p, 0.030f, 1.16f \u002B 0.07f * p );\n\t\t\t\t\t\tif ( v.GuideRenderer != null ) v.GuideRenderer.Tint = new Color( 0.22f, 0.92f, 1f, 0.62f );\n\t\t\t\t\t}\n\t\t\t\t\telse\n\t\t\t\t\t{\n\t\t\t\t\t\tv.Guide.LocalScale = Vector3.Zero;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tif ( !v.Swapping \u0026\u0026 !v.Spawning )\n\t\t\t\t\tv.Go.WorldScale = PieceShape( v.Type ) * CandyScale * scaleMul;\n\t\t\t}\n\t\t}\n\t}\n\n\tint PickTypeAvoidingImmediateMatch( int x, int y )\n\t{\n\t\tfor ( int attempt = 0; attempt \u003C 12; attempt\u002B\u002B )\n\t\t{\n\t\t\tint type = Game.Random.Int( 0, CandyTypeCount - 1 );\n\t\t\tbool badH = x \u003E= 2 \u0026\u0026 _types[x - 1, y] == type \u0026\u0026 _types[x - 2, y] == type;\n\t\t\tbool badV = y \u003E= 2 \u0026\u0026 _types[x, y - 1] == type \u0026\u0026 _types[x, y - 2] == type;\n\t\t\tif ( !badH \u0026\u0026 !badV ) return type;\n\t\t}\n\t\treturn Game.Random.Int( 0, CandyTypeCount - 1 );\n\t}\n\n\t// -------------------- helpers --------------------\n\n\tbool AreAdjacent( int x1, int y1, int x2, int y2 ) =\u003E Math.Abs( x1 - x2 ) \u002B Math.Abs( y1 - y2 ) == 1;\n\tbool InBounds( int x, int y ) =\u003E x \u003E= 0 \u0026\u0026 x \u003C Width \u0026\u0026 y \u003E= 0 \u0026\u0026 y \u003C Height;\n\n\tbool PressedEither( string a, string b ) =\u003E Pressed( a ) || Pressed( b );\n\n\tbool ActionPressed( params string[] actions )\n\t{\n\t\tforeach ( var action in actions )\n\t\t\tif ( Input.Pressed( action ) )\n\t\t\t\treturn true;\n\n\t\treturn false;\n\t}\n\n\tbool Pressed( string key )\n\t{\n\t\tbool down = Input.Keyboard.Down( key );\n\t\t_prevKeys.TryGetValue( key, out bool prev );\n\t\t_prevKeys[key] = down;\n\t\treturn down \u0026\u0026 !prev;\n\t}\n\n\tvoid ClearBoardObjects()\n\t{\n\t\tif ( _visuals == null ) return;\n\t\tfor ( int y = 0; y \u003C _visuals.GetLength( 1 ); y\u002B\u002B )\n\t\t\tfor ( int x = 0; x \u003C _visuals.GetLength( 0 ); x\u002B\u002B )\n\t\t\t\t_visuals[x, y]?.Go?.Destroy();\n\t\tforeach ( var burst in _bursts )\n\t\t{\n\t\t\tif ( burst.Go != null \u0026\u0026 burst.Renderer != null )\n\t\t\t\tReturnBurstObject( burst.Go );\n\t\t\telse\n\t\t\t\tburst.Go?.Destroy();\n\t\t}\n\t\tforeach ( var wave in _shockwaves ) wave.Go?.Destroy();\n\t\t_bursts.Clear();\n\t\t_shockwaves.Clear();\n\t}\n\n\tvoid CleanupDecor()\n\t{\n\t\tforeach ( var go in _decor ) go?.Destroy();\n\t\t_decor.Clear();\n\t}\n\n\tbool TryGetMainCamera( out CameraComponent cam )\n\t{\n\t\tcam = null;\n\t\tif ( Scene == null ) return false;\n\t\tforeach ( var c in Scene.GetAllComponents\u003CCameraComponent\u003E() )\n\t\t{\n\t\t\tif ( c.IsMainCamera ) { cam = c; return true; }\n\t\t\tcam ??= c;\n\t\t}\n\t\treturn cam != null;\n\t}\n\n\tvoid FrameMainCameraToBoard()\n\t{\n\t\tif ( !TryGetMainCamera( out var cam ) || cam.GameObject == null ) return;\n\t\tfloat boardW = Width * CellSpacing;\n\t\tfloat boardH = Height * CellSpacing;\n\t\tfloat verticalFov = 44f;\n\t\tfloat verticalFovRad = verticalFov * MathF.PI / 180f;\n\t\tfloat aspect = 16f / 9f;\n\t\tfloat targetW = boardW \u002B CellSpacing * 4.8f;\n\t\tfloat targetH = boardH \u002B CellSpacing * 6.4f;\n\t\tfloat distanceForHeight = (targetH * 0.5f) / MathF.Tan( verticalFovRad * 0.5f );\n\t\tfloat horizontalFovRad = 2f * MathF.Atan( MathF.Tan( verticalFovRad * 0.5f ) * aspect );\n\t\tfloat distanceForWidth = (targetW * 0.5f) / MathF.Tan( horizontalFovRad * 0.5f );\n\t\tfloat distance = MathF.Max( distanceForHeight, distanceForWidth ) * 1.45f;\n\t\tvar center = BoardOrigin \u002B new Vector3( 0f, 2f, 0f );\n\t\tvar camPos = center \u002B new Vector3( 0f, -distance, 0f );\n\t\tcam.GameObject.WorldPosition = camPos;\n\t\tcam.GameObject.WorldRotation = Rotation.LookAt( center - camPos, Vector3.Up );\n\t\tcam.FieldOfView = verticalFov;\n\t\tcam.BackgroundColor = new Color( 0.055f, 0.045f, 0.095f );\n\t\tcam.EnablePostProcessing = true;\n\t\tcam.ZNear = 1f;\n\t\tcam.ZFar = MathF.Max( cam.ZFar, 20000f );\n\t\t_activeCamera = cam;\n\t\t_baseFov = cam.FieldOfView;\n\t\t_baseCameraPos = cam.GameObject.WorldPosition;\n\t}\n\n\tvoid UpdateAmbience()\n\t{\n\t\tfloat t = Time.Now;\n\t\tif ( _orbitLightL != null )\n\t\t{\n\t\t\tfloat r = MathF.Max( Width, Height ) * CellSpacing * 0.7f;\n\t\t\t_orbitLightL.WorldPosition = BoardOrigin \u002B new Vector3( MathF.Cos( t * 0.7f ) * r, -CellSpacing * 1.2f, MathF.Sin( t * 0.7f ) * r );\n\t\t}\n\t\tif ( _orbitLightR != null )\n\t\t{\n\t\t\tfloat r = MathF.Max( Width, Height ) * CellSpacing * 0.7f;\n\t\t\t_orbitLightR.WorldPosition = BoardOrigin \u002B new Vector3( MathF.Cos( t * 0.7f \u002B MathF.PI ) * r, -CellSpacing * 1.2f, MathF.Sin( t * 0.7f \u002B MathF.PI ) * r );\n\t\t}\n\n\t\tif ( _trayInnerRenderer != null )\n\t\t{\n\t\t\tfloat r = 0.05f \u002B 0.025f * MathF.Sin( t * 0.55f );\n\t\t\tfloat g = 0.07f \u002B 0.025f * MathF.Sin( t * 0.55f \u002B 2f );\n\t\t\tfloat b = 0.12f \u002B 0.035f * MathF.Sin( t * 0.55f \u002B 4f );\n\t\t\tvar shift = new Color( r, g, b );\n\t\t\t_trayInnerRenderer.Tint = Color.Lerp( _trayBaseColor, shift, 0.45f );\n\t\t}\n\n\t}\n\n\tvoid UpdateCameraPunch()\n\t{\n\t\tif ( _activeCamera == null ) return;\n\t\tfloat dt = Time.Delta;\n\t\t_fovPunch = MathX.Lerp( _fovPunch, 0f, dt * 6f );\n\t\t_shakeAmount = MathX.Lerp( _shakeAmount, 0f, dt * 5f );\n\t\t_activeCamera.FieldOfView = _baseFov \u002B _fovPunch;\n\n\t\tif ( _shakeAmount \u003E 0.01f \u0026\u0026 _activeCamera.GameObject != null )\n\t\t{\n\t\t\tvar offset = new Vector3(\n\t\t\t\tGame.Random.Float( -1f, 1f ),\n\t\t\t\tGame.Random.Float( -1f, 1f ),\n\t\t\t\tGame.Random.Float( -1f, 1f ) ) * _shakeAmount;\n\t\t\t_activeCamera.GameObject.WorldPosition = _baseCameraPos \u002B offset;\n\t\t}\n\t\telse if ( _activeCamera.GameObject != null )\n\t\t{\n\t\t\t_activeCamera.GameObject.WorldPosition = _baseCameraPos;\n\t\t}\n\t}\n\n\tvoid PunchCamera( float fovDelta, float shake )\n\t{\n\t\tif ( !CameraShakeEnabled ) return;\n\t\t_fovPunch -= fovDelta; // negative FOV = zoom in\n\t\t_shakeAmount = MathF.Max( _shakeAmount, shake );\n\t}\n\n\t// Seamless-ish looping background music. Re-triggers when the clip ends; the\n\t// synthesized loop wraps at matching amplitude so the seam isn\u0027t audible.\n\tvoid UpdateMusic()\n\t{\n\t\tif ( !MusicEnabled || string.IsNullOrWhiteSpace( MusicSound ) )\n\t\t{\n\t\t\tif ( _music.IsValid() )\n\t\t\t{\n\t\t\t\t_music.Stop( 0.4f );\n\t\t\t\t_music = default;\n\t\t\t}\n\t\t\treturn;\n\t\t}\n\n\t\tif ( !_music.IsValid() || _music.IsStopped || _music.Finished )\n\t\t{\n\t\t\ttry\n\t\t\t{\n\t\t\t\t_music = Sound.Play( MusicSound );\n\t\t\t\tif ( _music.IsValid() )\n\t\t\t\t{\n\t\t\t\t\t_music.SpacialBlend = 0f;\n\t\t\t\t\t_music.Volume = MusicVolume;\n\t\t\t\t}\n\t\t\t}\n\t\t\tcatch\n\t\t\t{\n\t\t\t\t// Music asset missing/unsupported \u2014 silently continue without it.\n\t\t\t}\n\t\t}\n\t\telse\n\t\t{\n\t\t\t_music.Volume = MusicVolume;\n\t\t}\n\t}\n\n\tvoid PlayUiSound( string sound, float volume, float pitch )\n\t{\n\t\tif ( !AudioEnabled ) return;\n\t\tif ( string.IsNullOrWhiteSpace( sound ) || _audioCooldown \u003E 0f ) return;\n\t\ttry\n\t\t{\n\t\t\tvar handle = Sound.Play( sound, 0f );\n\t\t\thandle.Volume = volume;\n\t\t\thandle.Pitch = pitch;\n\t\t\thandle.SpacialBlend = 0f;\n\t\t\t_audioCooldown = 0.035f;\n\t\t}\n\t\tcatch\n\t\t{\n\t\t\t_audioCooldown = 0.2f;\n\t\t}\n\t}\n\n\tvoid EnsureSceneLighting()\n\t{\n\t\tif ( Scene == null ) return;\n\t\tforeach ( var l in Scene.GetAllComponents\u003CDirectionalLight\u003E() )\n\t\t\tif ( l != null ) return;\n\n\t\tvar lightGo = new GameObject( true, \u0022Auto Directional Light\u0022 );\n\t\tlightGo.Flags = GameObjectFlags.NotNetworked;\n\t\tlightGo.WorldRotation = Rotation.LookAt( new Vector3( 0.4f, -0.25f, -1f ).Normal, Vector3.Up );\n\t\tvar d = lightGo.AddComponent\u003CDirectionalLight\u003E();\n\t\td.LightColor = new Color( 0.95f, 0.98f, 1f );\n\t\td.Shadows = true;\n\t}\n\n\t// -------------------- easing --------------------\n\n\tstatic float EaseInOutCubic( float t ) =\u003E t \u003C 0.5f ? 4f * t * t * t : 1f - MathF.Pow( -2f * t \u002B 2f, 3f ) / 2f;\n\tstatic float EaseOutCubic( float t ) =\u003E 1f - MathF.Pow( 1f - t, 3f );\n\tstatic float EaseOutBack( float t )\n\t{\n\t\tconst float c1 = 1.70158f;\n\t\tconst float c3 = c1 \u002B 1f;\n\t\tfloat u = t - 1f;\n\t\treturn 1f \u002B c3 * u * u * u \u002B c1 * u * u;\n\t}\n}\n"},{"Ident":"verarp.colour_break","Path":"ui/controls/switchcontrol.razor.scss","FileName":"switchcontrol.razor.scss","PackageType":"game","CodeKind":"Game","AssetVersionId":292528,"IsPrivate":false,"Code":"\r\n.switchcontrol\r\n{\r\n    flex-direction: row;\r\n    width: 100px;\r\n    min-height: 24px;\r\n    align-items: center;\r\n    cursor: pointer;\r\n\r\n    .switch-frame\r\n    {\r\n        flex-grow: 0;\r\n        flex-shrink: 1;\r\n        width: 48px;\r\n        height: 16px;\r\n        background-color: #fff1;\r\n        margin: 0px 5px;\r\n        align-items: center;\r\n        border-radius: 100px;\r\n        transition: all 0.4s linear;\r\n\r\n        .switch-inner\r\n        {\r\n            position: relative;\r\n            flex-grow: 0;\r\n            flex-shrink: 1;\r\n            background-color: #999;\r\n            width: 25px;\r\n            height: 25px;\r\n            border-radius: 100px;\r\n            left: 20%;\r\n            transform: translateX( -50% );\r\n            transition: all 0.3s ease-out;\r\n        }\r\n    }\r\n\r\n    \u0026.active\r\n    {\r\n        .switch-frame\r\n        {\r\n            background-color: #fffa;\r\n        }\r\n\r\n        .switch-inner\r\n        {\r\n            left: 80%;\r\n            background-color: #fff;\r\n        }\r\n    }\r\n}\r\n"},{"Ident":"verarp.colour_break","Path":"styles/form/_colorproperty.scss","FileName":"_colorproperty.scss","PackageType":"game","CodeKind":"Game","AssetVersionId":292528,"IsPrivate":false,"Code":"\r\n\r\n.colorproperty\r\n{\r\n\talign-items: center;\r\n\tposition: relative;\r\n\r\n\t.colorsquare\r\n\t{\r\n\t\twidth: 20px;\r\n\t\theight: 20px;\r\n\t\tborder-radius: 4px;\r\n\t\tmargin-right: 8px;\r\n\t\tposition: absolute;\r\n\t\tleft: 7px;\r\n\t\tz-index: 1;\r\n\t\tcursor: pointer;\r\n\t}\r\n\r\n\t\u003E .textentry:not( .a.b.c )\r\n\t{\r\n\t\tpadding-left: 36px;\r\n\t}\r\n}"},{"Ident":"verarp.colour_break","Path":"ui/menupanel.razor.scss","FileName":"menupanel.razor.scss","PackageType":"game","CodeKind":"Game","AssetVersionId":292528,"IsPrivate":false,"Code":"\r\nmenupanel\r\n{\r\n    position: absolute;\r\n    z-index: 1000;\r\n    pointer-events: all;\r\n    font-size: 12px;\r\n    flex-shrink: 0;\r\n\r\n    .background\r\n    {\r\n        position: absolute;\r\n        left: -5000px;\r\n        right: -5000px;\r\n        top: -5000px;\r\n        bottom: -5000px;\r\n    }\r\n\r\n    \u003E .inner\r\n    {\r\n        min-width: 200px;\r\n        min-height: 20px;\r\n        flex-direction: column;\r\n        font-family: Poppins;\r\n        font-weight: bold;\r\n        border-radius: 10px;\r\n        box-shadow: 5px 5px 30px #000e;\r\n        background-color: #2a2a2a;\r\n        flex-shrink: 0;\r\n\r\n        .spacer\r\n        {\r\n            height: 1px;\r\n            background-color: #0005;\r\n        }\r\n\r\n        .option\r\n        {\r\n            color: #fffa;\r\n            padding: 0px 8px;\r\n            cursor: pointer;\r\n            flex-shrink: 0;\r\n            height: 32px;\r\n\r\n            \u0026:first-child\r\n            {\r\n                border-top-left-radius: 10px;\r\n                border-top-right-radius: 10px;\r\n            }\r\n\r\n            \u0026:last-child\r\n            {\r\n                border-bottom-left-radius: 10px;\r\n                border-bottom-right-radius: 10px;\r\n            }\r\n\r\n            .icon\r\n            {\r\n                padding: 8px;\r\n                font-family: Material Icons;\r\n                justify-content: center;\r\n                align-items: center;\r\n                flex-shrink: 0;\r\n            }\r\n\r\n            .text\r\n            {\r\n                padding: 8px;\r\n                flex-shrink: 0;\r\n            }\r\n\r\n            \u0026:hover\r\n            {\r\n                background-color: #3472e6;\r\n                color: #f5f8fe;\r\n            }\r\n        }\r\n    }\r\n}\r\n"},{"Ident":"verarp.colour_break","Path":"ui/controls/color/colorcontrol.cs.scss","FileName":"colorcontrol.cs.scss","PackageType":"game","CodeKind":"Game","AssetVersionId":292528,"IsPrivate":false,"Code":"ColorControl\r\n{\r\n\tgap: 0.5rem;\r\n\tflex-grow: 1;\r\n\tpointer-events: all;\r\n\tbackground-color: #000a;\r\n\tborder-radius: 4px;\r\n\tpadding: 2px;\r\n\theight: 32px;\r\n}\r\n\r\nColorControl TextEntry\r\n{\r\n\tflex-grow: 1;\r\n\tflex-shrink: 0;\r\n\tcolor: #aaa;\r\n\tfont-size: 1.2rem;\r\n\r\n\t\u0026:hover, \u0026:focus\r\n\t{\r\n\t\tcolor: #ddd;\r\n\r\n\t\t.icon\r\n\t\t{\r\n\t\t\tcolor: #3af;\r\n\t\t}\r\n\t}\r\n\r\n\t\u0026:active\r\n\t{\r\n\t\tcolor: white;\r\n\t}\r\n}\r\n\r\nColorControl \u003E .colorswatch\r\n{\r\n\taspect-ratio: 1;\r\n\tborder-radius: 4px;\r\n\theight: 100%;\r\n\tflex-shrink: 0;\r\n\tcursor: pointer;\r\n\tborder: 2px solid #000;\r\n}"},{"Ident":"verarp.colour_break","Path":"ui/components/packagefilters.razor.scss","FileName":"packagefilters.razor.scss","PackageType":"game","CodeKind":"Game","AssetVersionId":292528,"IsPrivate":false,"Code":"\r\n@import \u0022/styles/_theme.scss\u0022;\r\n\r\n.packagefilter\r\n{\r\n\twidth: 100%;\r\n\tflex-shrink: 0;\r\n\r\n\t.left\r\n\t{\r\n\t\tflex-grow: 1;\r\n\t\tflex-shrink: 0;\r\n\t\tgap: 16px;\r\n\t}\r\n\r\n\t.right\r\n\t{\r\n\t\tflex-grow: 1;\r\n\t\tflex-shrink: 0;\r\n\t\tgap: 16px;\r\n\t}\r\n}\r\n\r\n.packagefilter textentry\r\n{\r\n\tflex-grow: 1;\r\n\tpadding: 8px 12px;\r\n\tpointer-events: all;\r\n\r\n\tLabel\r\n\t{\r\n\t\tmargin-left: 26px;\r\n\t}\r\n\r\n\ticonpanel\r\n\t{\r\n\t\tposition: absolute;\r\n\t\tleft: 12px;\r\n\t\topacity: 0.3;\r\n\t\tfont-size: $text-large;\r\n\t}\r\n}\r\n\r\n\t.packagefilterfacet, .packagefilter textentry\r\n\t{\r\n\t\tbackground-color: rgba($default-950, 0.3);\r\n\t\tcolor: $default-text;\r\n\t\toutline: 1px solid $default-border;\r\n\t\ttransition: all 150ms $easing;\r\n\t\tborder-radius: $rounding-default;\r\n\t\tpadding: 4px 12px;\r\n\t\tgap: 16px;\r\n\t\tflex-shrink: 0;\r\n\t\tfont-size: 14px;\r\n\t\tcursor: pointer;\r\n\t\talign-items: center;\r\n\r\n\t\t.clear-button\r\n\t\t{\r\n\t\t\theight: 100%;\r\n\t\t\tmargin-right: -8px;\r\n\t\t\talign-items: center;\r\n\t\t\tpadding: 0px 4px;\r\n\r\n\t\t\t\u0026:hover\r\n\t\t\t{\r\n\t\t\t\tcolor: red;\r\n\t\t\t\tborder-radius: 100%;\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\t\u0026.is-active\r\n\t\t{\r\n\t\t\tbackground-color: $default-700;\r\n\t\t}\r\n\r\n\t\t\u0026:not(.is-active)\r\n\t\t{\r\n\t\t\t\u0026:hover\r\n\t\t\t{\r\n\t\t\t\toutline: 1px solid $default-50;\r\n\t\t\t}\r\n\t\t}\r\n\t}"}]}