ui/theme.scss
// ============================================================================
// The Deck - theme tokens.
//
// A green-felt casino table: a softly-lit felt backdrop, near-black panels that
// let the table read through, gold for everything you act on, and a warm ivory
// serif for every headline. Every component below composes from these tokens, so
// re-skinning the whole game is a matter of editing the values up here.
// ============================================================================
$serif: "Georgia"; // headlines, game titles, player names - the casino "voice"
$sans: "Archivo"; // eyebrows, body copy, buttons, stats - everything functional
$font: $sans; // legacy alias: older markup referenced $font for the base face
// --- Felt backdrop ---------------------------------------------------------
// A centred glow over a deep green that darkens to the edges (radial-gradient in
// s&box is always centre-anchored). The menu paints this solid; in-game panels
// sit translucent over the real 3D table instead.
$felt-glow: #36694d;
$felt: #1f4433;
$felt-edge: #0f2417;
// Card-art panel behind the launcher's little playing cards.
$art-top: #2c5740;
$art-bottom: #14301f;
// --- Surfaces --------------------------------------------------------------
// Near-black with a faint warm/green cast. Translucent so the table reads through.
$panel: rgba(11, 17, 14, .92); // primary surface (status card, info zones)
$panel-2: rgba(19, 27, 23, .95); // raised surface (secondary button)
$panel-3: rgba(14, 21, 17, .9); // list row / pill
$panel-deep: rgba(8, 13, 11, .9); // detail / modal panel
$chip: rgba(25, 34, 29, .95); // stat chip
// --- Gold accent -----------------------------------------------------------
// The brand accent: links, eyebrows, taglines, the primary call-to-action, the
// "it's your turn / your seat" highlight.
$gold: #d8b56b;
$gold-bright: #ecd396; // top of the primary-button gradient
$gold-deep: #bd9445; // bottom of the primary-button gradient
$gold-soft: #e7d6a8; // warm gold text
$on-gold: #20180a; // text/icon sitting on a gold fill
// --- Text ------------------------------------------------------------------
$text: #f1ead8; // primary cream
$text-soft: #e8e2d2; // button label
$text-dim: #a9b3a6; // body copy (cool sage)
$text-mut: #8b958a; // eyebrow / stat label
$text-faint: #6b746a; // chevrons
$text-off: #565d55; // disabled
// --- Playing-card faces (the launcher art) ---------------------------------
$card-face: #f6f2e6; // ivory
$card-red: #b23330; // hearts / diamonds
$card-black: #1c2530; // spades / clubs
// --- Status colours --------------------------------------------------------
$green: #6fd39a; // winnings / positive delta / committed bet
$red: #b23330; // playing-card red, "bad" badges
$red-text: #e8736b; // loss-tone text on a dark panel
// Legacy red-gradient aliases (no longer used by the gold theme, kept defined so
// any stray reference still compiles). Point them at the gold ramp.
$red-bright: $gold-bright;
$red-deep: $gold-deep;
$red-soft: $gold-soft;
// Hairlines - a touch warmer than pure white so they sit on felt without glare.
$line: rgba(236, 230, 214, .08);
$line-soft: rgba(236, 230, 214, .12);
// Background aliases (menu fallbacks).
$bg: $felt-edge;
$bg-raise: $felt;
// Rounded corners are back - the table is soft, not industrial.
$r-sm: 10px; // buttons, chips, pills, badges
$r-md: 14px; // status card, seat tag, list rows
$r-lg: 16px; // cards, detail panels
$r-xl: 20px; // scene frames
// Safe margin kept clear around every screen edge - use this everywhere so panels line up.
$deadzone: 72px;
// Elevation. s&box has no `inset` box-shadow (the engine never uses one), so these are plain drop
// shadows only - definition comes from borders + the gradient, not an inner highlight.
@mixin elevate
{
box-shadow: 0 8px 22px rgba(0,0,0,.45);
}
@mixin elevate-btn
{
box-shadow: 0 4px 12px rgba(0,0,0,.35);
}
// The primary call-to-action wears a warm gold glow, not just a drop shadow.
@mixin elevate-primary
{
box-shadow: 0 0px 20px rgba(216,181,107,.32);
}
@mixin elevate-panel
{
box-shadow: 0 18px 44px rgba(0,0,0,.5);
}
// Put .cgui on a panel root to inherit the font + base colour.
.cgui
{
font-family: $sans;
color: $text;
}
.cg-status
{
font-family: $serif;
font-size: 24px;
font-weight: 400;
color: $text;
text-align: center;
text-shadow: 0 2px 8px rgba(0,0,0,.6);
}
.cg-eyebrow
{
font-family: $sans;
font-size: 11px;
font-weight: 800;
letter-spacing: 3px;
text-transform: uppercase;
color: $gold;
}
.cg-note
{
font-family: $sans;
font-size: 14px;
color: $text-dim;
}
// Big display title (launcher / headers). The casino voice: serif, sentence-case, calm.
.cg-display
{
font-family: $serif;
font-size: 52px;
font-weight: 400;
letter-spacing: 0;
line-height: 1.05;
color: $text;
}
// Body copy.
.cg-body
{
font-family: $sans;
font-size: 14px;
font-weight: 400;
line-height: 1.6;
color: $text-dim;
}
// A bottom-of-screen row: a scoreboard "board" followed by action buttons. The
// row stretches its children to equal height.
.cg-bar
{
flex-direction: row;
align-items: stretch;
gap: 12px;
}
// Scoreboard - a clipped row of segments divided by hairlines.
.cg-board
{
flex-direction: row;
align-items: stretch;
border-radius: $r-md;
overflow: hidden;
@include elevate;
.seg
{
flex-direction: column;
justify-content: center;
padding: 9px 16px;
background-color: $panel-2;
border-left: 0.15px solid $line;
.k
{
font-family: $sans;
font-size: 8px;
font-weight: 700;
letter-spacing: 1px;
text-transform: uppercase;
color: $text-mut;
}
.v
{
font-family: $serif;
font-size: 18px;
font-weight: 700;
color: $text;
}
// First segment has no divider.
&.lead
{
border-left-width: 0;
}
// Brand/title segment.
&.brand
{
background-color: $panel;
justify-content: center;
.title
{
font-family: $serif;
font-size: 16px;
font-weight: 700;
letter-spacing: 0;
color: $text;
}
}
// The "you" highlight - gold rule + warm label.
&.you
{
background-color: rgba(34, 28, 16, .96);
border-left: 3px solid $gold;
.k
{
color: $gold-soft;
}
}
}
}
.cg-btn
{
flex-direction: row;
align-items: center;
justify-content: center;
gap: 8px;
padding: 13px 24px;
font-family: $sans;
font-size: 14px;
font-weight: 800;
letter-spacing: 1.5px;
text-transform: uppercase;
color: $text-soft;
background-color: $panel-2;
border: 0.15px solid $line-soft;
border-radius: $r-sm;
cursor: pointer;
pointer-events: all;
transition: all .1s ease;
@include elevate-btn;
&:hover
{
filter: brightness(1.35);
}
&:active
{
filter: brightness(0.85);
transform: translateY(1px);
box-shadow: 0 2px 6px rgba(0,0,0,.35);
}
// Primary - the recommended move "wears the gold".
&.primary
{
padding: 13px 30px;
color: $on-gold;
background-color: $gold;
background-image: linear-gradient(to bottom, $gold-bright, $gold-deep);
border-color: transparent;
&:hover
{
filter: brightness(1.12);
box-shadow: 0 0px 26px rgba(216,181,107,.5);
}
&:active
{
filter: brightness(0.94);
transform: translateY(1px);
box-shadow: 0 0px 12px rgba(216,181,107,.28);
}
}
// Ghost - quiet, for menu/leave.
&.ghost
{
color: $text-dim;
background-color: rgba(19, 27, 23, .6);
border-color: $line;
box-shadow: none;
&:hover
{
color: $text-soft;
filter: none;
}
&:active
{
color: $text-soft;
background-color: rgba(19, 27, 23, .9);
filter: none;
transform: translateY(1px);
box-shadow: none;
}
}
// Compact icon button.
&.icon
{
padding: 13px 17px;
}
// Greyed out and not clickable - stays in place while temporarily unavailable.
&.disabled
{
color: $text-off;
background-color: rgba(19, 27, 23, .45);
background-image: none;
border-color: rgba(236, 230, 214, .05);
box-shadow: none;
pointer-events: none;
.ico { color: $text-off; }
&:hover { filter: none; }
}
// Material Icons glyph inside a button (set via GameAction.Icon). Reset the button's uppercase +
// letter-spacing - both break the ligature lookup (it only matches lowercase "undo" with no tracking).
.ico
{
font-family: "Material Icons";
font-size: 18px;
line-height: 1;
text-transform: none;
letter-spacing: 0;
}
}
// A connected cluster of actions (e.g. chip denominations, undo/redo). The container carries the
// rounding + elevation; the buttons inside become flat segments split by hairline dividers.
.cg-group
{
flex-direction: row;
align-items: stretch;
gap: 1px; // dividers = the group's background showing through the gaps
background-color: rgba(236, 230, 214, .1);
border: 0.15px solid $line-soft; // same outline as a standalone button, around the whole cluster
border-radius: $r-sm;
overflow: hidden;
@include elevate-btn;
// Segments are borderless - the 1px gap (filled by the group background) is the only divider, so
// there's no per-button border doubling up at the intersections.
.cg-btn
{
border: none;
border-radius: 0;
box-shadow: none;
}
}
// Keybind chip shown inside a button.
.cg-key
{
align-self: center;
font-family: $sans;
font-size: 9px;
font-weight: 700;
color: rgba(236, 230, 214, .5);
border: 0.15px solid rgba(236, 230, 214, .2);
border-radius: 5px;
padding: 1px 5px;
}
.cg-btn.primary .cg-key
{
color: rgba(32, 24, 10, .7);
border-color: rgba(32, 24, 10, .35);
}
// A small gold tag - feature badges over card art, etc.
.cg-tag
{
align-self: center;
padding: 4px 12px;
font-family: $sans;
font-size: 10px;
font-weight: 800;
letter-spacing: 1.5px;
text-transform: uppercase;
color: $on-gold;
background-color: $gold;
border-radius: $r-sm;
}
.cg-pill
{
flex-direction: row;
align-items: center;
gap: 8px;
padding: 9px 15px;
border-radius: $r-sm;
background-color: $panel-3;
border: 0.15px solid $line;
.dot
{
width: 14px;
height: 14px;
border-radius: 50%;
background-color: $gold;
}
.amt
{
font-family: $sans;
font-size: 13px;
font-weight: 800;
color: $text;
}
}
.cg-hint
{
flex-direction: row;
align-items: center;
gap: 9px;
padding: 9px 16px;
border-radius: $r-sm;
background-color: $panel;
border: 0.15px solid $line;
@include elevate-btn;
// "HINT" as a small gold eyebrow - gold text, not a gold block.
.label
{
font-family: $sans;
font-size: 10px;
font-weight: 800;
letter-spacing: 1.5px;
text-transform: uppercase;
color: $gold;
}
.body
{
font-family: $sans;
font-size: 14px;
font-weight: 700;
color: $text;
}
}
.cg-stat
{
flex-direction: column;
align-items: stretch;
border-radius: $r-sm;
overflow: hidden;
.k
{
padding: 9px 13px;
background-color: $chip;
font-family: $sans;
font-size: 8px;
font-weight: 700;
letter-spacing: 1px;
text-transform: uppercase;
color: $text-mut;
height: 8px;
}
.v
{
padding: 9px 13px;
background-color: $chip;
font-family: $sans;
font-size: 14px;
font-weight: 800;
color: $text;
}
}
.cg-item
{
flex-direction: row;
align-items: center;
gap: 15px;
padding: 17px 18px;
border-radius: $r-md;
background-color: $panel-3;
border: 0.15px solid $line;
cursor: pointer;
pointer-events: all;
transition: all .1s ease;
.num
{
font-family: $sans;
font-size: 14px;
font-weight: 800;
letter-spacing: 1px;
color: $text-mut;
}
.name
{
flex-grow: 1;
font-family: $serif;
font-size: 20px;
font-weight: 700;
color: $text-soft;
}
.chev
{
font-size: 16px;
color: $text-faint;
}
&:hover
{
filter: brightness(1.3);
border-color: $line-soft;
}
// Selected - the highlighted game wears the gold rule.
&.selected
{
background-color: rgba(34, 28, 16, .9);
border-color: $gold;
.num { color: $gold-soft; }
.name { color: $text; }
.chev { color: $gold; }
}
&.disabled
{
background-color: rgba(14,21,17,.5);
border-color: rgba(236,230,214,.04);
cursor: default;
pointer-events: none;
.num,
.name { color: $text-off; }
}
}
.cg-panel
{
background-color: $panel-deep;
border: 0.15px solid $line;
border-radius: $r-lg;
@include elevate-panel;
}
.cg-result
{
flex-direction: row;
align-items: stretch;
border-radius: $r-md;
overflow: hidden;
@include elevate;
.outcome
{
flex-direction: column;
justify-content: center;
padding: 14px 26px;
background-image: linear-gradient(to bottom, $gold-bright, $gold-deep);
.k
{
font-family: $sans;
font-size: 10px;
font-weight: 800;
letter-spacing: 2px;
text-transform: uppercase;
color: rgba(32,24,10,.7);
}
.v
{
font-family: $serif;
font-size: 26px;
font-weight: 700;
color: $on-gold;
}
}
.payout
{
flex-direction: column;
justify-content: center;
padding: 14px 24px;
background-color: $panel;
.v
{
font-family: $serif;
font-size: 30px;
font-weight: 700;
color: $green;
}
}
}