@layer base;

/* Roboto, served from this server instead of Google's, so the browser opens
   no outside connection before it can draw text and keeps the files for the
   thirty days our static files are cached. One variable file per alphabet
   covers every weight from 100 to 900. The maths and symbol alphabets are
   deliberately left out: they cost 60 KB and only a few arrows and emoji
   fall in them, which the reader's own font draws. */
@font-face {
  font-family: 'Roboto';
  font-style: normal;
  font-weight: 100 900;
  font-stretch: 100%;
  font-display: swap;
  src: url("../fonts/roboto-latin.665db5e157d2.woff2") format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: 'Roboto';
  font-style: normal;
  font-weight: 100 900;
  font-stretch: 100%;
  font-display: swap;
  src: url("../fonts/roboto-latin-ext.a6323dda0842.woff2") format('woff2');
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
@font-face {
  font-family: 'Roboto';
  font-style: italic;
  font-weight: 100 900;
  font-stretch: 100%;
  font-display: swap;
  src: url("../fonts/roboto-latin-italic.2465bec3a1d5.woff2") format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: 'Roboto';
  font-style: italic;
  font-weight: 100 900;
  font-stretch: 100%;
  font-display: swap;
  src: url("../fonts/roboto-latin-ext-italic.98cef6d26378.woff2") format('woff2');
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}

:root {
  /* Says we answer for a dark phone ourselves, which keeps Chrome, Edge and
     Samsung from repainting our colours. We answer by not changing: there is
     no dark set anywhere in this file, so the site stays as drawn. A page
     that claims only "light" is the one those browsers repaint. */
  color-scheme: light dark;

  /* Color Tokens */
  --bg-primary: #F2E6Ac;
  --bg-footer: #36454F;
  --accent-teal: #008080;
  --accent-gold: #D4AF37;
  --accent-activity: #199619; /* activity: online member, copy, live action */

  /* Neutral ramp -- surfaces, lines and inks for the light-themed apps.
     Every value here is a shade the project already used most; none are
     invented. The dark faceplate apps (Stopwatch, WallPro, Wall, Stars,
     Place, Digital Store) use the dark ramp below. */
  --surface:     #ffffff;   /* page and card white */
  --surface-2:   #f5f5f5;   /* subtle raised panel */
  --surface-3:   #eeeeee;   /* wells, alternate rows */
  --line:        #dddddd;   /* ordinary border */
  --line-strong: #cccccc;   /* divider that needs to be seen */
  --ink:         #1a1a1a;   /* headings */
  --ink-2:       #666666;   /* secondary text */
  --ink-3:       #999999;   /* muted text, placeholders */
                            /* body text stays --text-main */
  --text-main: #333;
  
  /* ---------------------------------------------------------------
     Dark ramp -- the six faceplate apps (Stopwatch, WallPro, Wall,
     Stars, Place, Digital Store) plus every dark panel elsewhere.
     #1d262c was already shared by 25 apps before it had a name. */
  --dark-bg:      #16161c;   /* dark page ground */
  --dark-surface: #1d262c;   /* raised dark panel, card, header */
  --dark-line:    #2f3a42;   /* border on a dark surface */
  --dark-ink:     #c4c4cd;   /* text on dark */
  --dark-ink-2:   #8e8e99;   /* secondary text on dark */

  /* Gold recipe -- the house palette the staff pages settled on. */
  --gold-bright:  #f0a830;   /* lit gold: active state, dark-app accent */
  --gold-light:   #ffd666;   /* gold highlight, hover */
  --gold-deep:    #6c4c24;   /* gold border, engraved edge */
  --gold-dark:    #1a1308;   /* warm dark ground under gold */
  --gold-dark-2:  #2a2118;   /* warm dark raised panel */
  --cream:        #f1ecda;   /* parchment surface */
  --cream-2:      #decebe;   /* parchment shade, inset */

  /* Status -- these had no token, so every app picked its own red and
     amber. Success stays --accent-activity. */
  --danger:       #E60000;   /* error, destructive, loss */
  --warning:      #FFC107;   /* caution, pending, expiring */

  /* Pink -- load-bearing in 15 apps (Blip, chat, album, profile). */
  --accent-pink:      #ff7ab8;
  --accent-pink-soft: #ff9cc9;

  /* The catalog/feedback button pair. Salmon is a hover and active state,
     not a danger colour -- mapping it to --danger turned four apps' buttons
     red. Kept together so a palette pass cannot split them again. */
  --salmon:       #FA9386;   /* button hover + active */
  --blue-btn:     #155E95;   /* button resting ground */

  /* Shadow -- 180 hand-written box-shadows, 12 different alphas. */
  --shadow-rgb: 0, 0, 0;
  --shadow-sm:  0 1px 3px rgba(var(--shadow-rgb), .10);
  --shadow-md:  0 4px 12px rgba(var(--shadow-rgb), .30);
  --shadow-lg:  0 10px 30px rgba(var(--shadow-rgb), .50);

  /* Pressed and hover shades -- a button must darken, not dim. */
  --accent-teal-dark: #0A6E6E;
  --accent-gold-dark: #B8912E;
  --danger-dark:      #B30000;
  --activity-dark:    #147714;
  --warning-dark:     #D9A406;
  --accent-pink-dark: #E85A9C;
  --disabled-bg:      #cccccc;   /* off is its own colour, never a faded on */
  --disabled-ink:     #767676;

  /* Hero gradient -- pasted into 6 apps. Named so it can be found. */
  --grad-hero-a: #667eea;
  --grad-hero-b: #764ba2;

  /* Layout Tokens */
  --container-width: 1400px;
  --gutter: 1rem;
}

@media (max-width: 1400px) {
  :root {
    --gutter: 0;
  }
}

@layer base {

  body {
    font-family: 'Roboto', sans-serif;
    margin: 0;
    background-color: var(--bg-primary);
    color: var(--text-main);
    /* Modern Sticky Footer Logic */
    display: flex;
    flex-direction: column;
    min-height: 100vh;
    overflow-x: hidden;
  } 
  
  /* The browser draws monospace one size smaller than everything else, which
     lands under the 14px floor on its own. Say the size instead of taking it. */
  pre, code, kbd, samp {
    font-size: 14px;
  }

  /* A button the browser draws for itself starts under the floor too, so a
     page that styles a button without naming a size still reads. The
     browser also gives it its own font (Arial), not the page's: a button
     that names no font of its own is Roboto like everything else. */
  button {
    font-size: 14px;
    font-family: 'Roboto', sans-serif;
  }

  .container {
    width: 100%;
    max-width: var(--container-width);
    margin: 0 auto;
    padding: 0 var(--gutter);
    box-sizing: border-box; /* Crucial: includes padding in width */
  }

  .dashboard-wrapper {
    flex: 1; /* This pushes the footer to the absolute bottom */
    display: flex;
    flex-direction: column;
  }

  .main-content {
    width: 100%;
    /* flex: 1 removed from here and moved to wrapper */
  }

  /* Screen-reader only — visible to crawlers, hidden visually */
  .sr-only {
    position: absolute;
    width: 1px;
    height: 1px;
    padding: 0;
    margin: -1px;
    overflow: hidden;
    clip: rect(0, 0, 0, 0);
    white-space: nowrap;
    border: 0;
  }

  footer {
    background-color: var(--bg-footer);
    border-top: 2px solid var(--accent-teal);
    color: var(--accent-gold);
    padding: 0.4rem 0;
    text-align: center;
  }

  footer .container {
    display: flex;
    justify-content: center;
    align-items: center;
  }


  .cart-icon {
    position: relative;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    background-color: #fff;
    border-radius: 50%;
    width: 32px;
    height: 32px;
    font-size: 20px;
    box-shadow: 0 2px 4px rgba(0,0,0,0.1);
  }

  .cart-icon .cart-total-items {
    position: absolute;
    top: -5px;
    right: -5px;
    width: 18px;
    height: 18px;
    background-color: #e44; /* Standard notification red */
    color: #fff;
    font-size: 14px;
    font-weight: bold;
    display: flex;
    align-items: center;
    justify-content: center;
    border-radius: 50%;
    box-shadow: 0 1px 2px rgba(0,0,0,0.2);
  }

  .messages-container {
    width: 100%;
    max-width: var(--container-width);
    margin: 0.3rem auto;
    padding: 0 var(--gutter);
    box-sizing: border-box;
  }

  /* ==========================================================================
     Status strip -- one shape for every message the site tells a person, from
     the Django messages framework to an app's own inline notice. A vivid edge
     carries the meaning; the text stays full-strength ink, never a washed tint.
     ========================================================================== */
  .alert {
    padding: 0.55rem 0.8rem;
    margin-bottom: 0.75rem;
    border: 1px solid var(--line);
    border-left: 4px solid var(--accent-teal);
    border-radius: 4px;
    background-color: var(--surface);
    color: var(--text-main);
    font-size: 0.9rem;
    line-height: 1.4;
  }
  .alert strong,
  .alert b { color: var(--ink); }

  .alert-success            { border-left-color: var(--accent-activity); }
  .alert-error,
  .alert-danger             { border-left-color: var(--danger); }
  .alert-warning            { border-left-color: var(--warning); }
  .alert-info,
  .alert-debug              { border-left-color: var(--accent-teal); }

  /* On a dark panel the same strip flips ground and ink, not strength. */
  .alert--on-dark {
    background-color: var(--dark-surface);
    color: var(--dark-ink);
    border-color: var(--dark-line);
  }

  @media (max-width: 480px) {
    .alert { padding: 0.5rem 0.6rem; font-size: 0.875rem; }
  }


  /* Staff inline editing hints */
  [contenteditable][data-key] {
    cursor: text;
  }
  [contenteditable][data-key]:hover {
    outline: 1px dashed rgba(184, 150, 46, 0.45);
    outline-offset: 4px;
  }

  /* ==========================================================================
     Buttons -- the one family. Every app used to ship its own .btn; nine files
     defined it and the last one loaded won. Geometry lives here, so an app only
     ever adds position, never paint.
     ========================================================================== */
  .btn {
    display: inline-block;
    padding: 0.75rem 1.5rem;
    border: none;
    border-radius: 4px;
    font-family: inherit;
    font-size: 1rem;
    font-weight: 600;
    line-height: 1.5;
    text-align: center;
    text-decoration: none;
    color: var(--surface);
    background-color: var(--accent-teal);
    cursor: pointer;
    transition: background-color .2s ease, transform .1s ease, box-shadow .2s ease;
    user-select: none;
    -webkit-appearance: none;
    appearance: none;
  }
  .btn:hover {
    background-color: var(--accent-teal-dark);
    transform: translateY(-2px);
    box-shadow: var(--shadow-md);
  }
  .btn:active {
    transform: translateY(0);
    box-shadow: var(--shadow-sm);
  }
  .btn:focus-visible {
    outline: 2px solid var(--accent-gold);
    outline-offset: 2px;
  }

  /* Gold -- the premium action: buy, claim, enter. */
  .btn--gold        { background-color: var(--accent-gold); color: var(--ink); }
  .btn--gold:hover  { background-color: var(--accent-gold-dark); }

  /* Danger -- delete, cancel, forfeit. */
  .btn--danger       { background-color: var(--danger); }
  .btn--danger:hover { background-color: var(--danger-dark); }

  /* Ghost -- the quiet second action beside a real one. */
  .btn--ghost {
    background-color: transparent;
    color: var(--accent-teal);
    border: 2px solid var(--accent-teal);
    padding: calc(0.75rem - 2px) calc(1.5rem - 2px);
  }
  .btn--ghost:hover { background-color: var(--accent-teal); color: var(--surface); }

  /* Sizes */
  .btn--sm { padding: 0.4rem 0.9rem;  font-size: 0.875rem; }
  .btn--lg { padding: 1rem 2rem;      font-size: 1.125rem; }
  .btn--block { display: block; width: 100%; }

  /* Off is its own colour, not a faded on. */
  .btn:disabled,
  .btn[disabled],
  .btn--off {
    background-color: var(--disabled-bg);
    color: var(--disabled-ink);
    cursor: not-allowed;
    transform: none;
    box-shadow: none;
  }
  .btn:disabled:hover,
  .btn[disabled]:hover,
  .btn--off:hover { background-color: var(--disabled-bg); transform: none; box-shadow: none; }

  @media (max-width: 480px) {
    .btn     { padding: 0.65rem 1rem; font-size: 0.95rem; }
    .btn--lg { padding: 0.8rem 1.25rem; font-size: 1rem; }
  }

  /* ==========================================================================
     Card -- one panel. An app adds its own grid position and inner layout;
     the surface, the edge and the lift all come from here.
     ========================================================================== */
  .card {
    background-color: var(--surface);
    border: 1px solid var(--line);
    border-radius: 8px;
    box-shadow: var(--shadow-sm);
    padding: 1rem;
  }
  .card--flat    { box-shadow: none; }
  .card--raised  { box-shadow: var(--shadow-md); }
  .card--gold    { border: 2px solid var(--gold-deep); background-color: var(--cream); }
  .card--dark    { background-color: var(--dark-surface); border-color: var(--dark-line); color: var(--dark-ink); }
  .card__head    { font-weight: 600; color: var(--ink); margin-bottom: .5rem; }

  @media (max-width: 480px) {
    .card { padding: 0.75rem; border-radius: 6px; }
  }

  /* ==========================================================================
     Form field -- one field. The heavy dark edge is the house look the staff
     pages settled on; focus answers in gold so the eye lands on the live field.
     ========================================================================== */
  /* The root says "light dark" to keep browser auto-dark away from the page.
     The parts the browser draws itself -- date pickers, dropdown lists,
     text fields -- must not take that as licence to go dark, so they are
     told plainly to stay light. Buttons are deliberately left out: they
     carry our own colours, and a phone browser reads an element marked
     light-only as one to repaint, which took the ink out of the gold
     buttons on the landing page. */
  input, select, textarea, [contenteditable] { color-scheme: light; }

  /* The same "light dark" hands a link with no colour of its own the
     browser's dark-mode blue (#9E9EFF), faded on our cream. Such links keep
     the plain light-mode colours; any colour a page sets still wins. */
  :where(a:link) { color: #0000EE; }
  :where(a:visited) { color: #551A8B; }

  :where(input:not([type="checkbox"]):not([type="radio"]):not([type="file"]):not([type="range"]):not([type="submit"]):not([type="button"])),
  :where(select),
  :where(textarea),
  :where(.form-control),
  :where(.form-input) {
    box-sizing: border-box;
    padding: 10px 12px;
    background-color: var(--surface);
    color: var(--text-main);
    border: 2px solid var(--dark-surface);
    border-radius: 4px;
    font-family: inherit;
    font-size: 1rem;
    line-height: 1.4;
    transition: border-color .15s ease, box-shadow .15s ease;
  }
  :where(input:focus),
  :where(select:focus),
  :where(textarea:focus),
  :where(.form-control:focus),
  :where(.form-input:focus) {
    outline: none;
    border-color: var(--accent-gold);
    box-shadow: 0 0 0 3px rgba(212, 175, 55, 0.25);
  }
  :where(input, textarea)::placeholder { color: var(--ink-3); }

  /* Off is its own colour, not a faded on. */
  :where(input:disabled, select:disabled, textarea:disabled, .form-control:disabled) {
    background-color: var(--disabled-bg);
    color: var(--disabled-ink);
    border-color: var(--line-strong);
    cursor: not-allowed;
  }
  /* A field the server rejected. */
  :where(.field-error input, input.is-invalid, select.is-invalid, textarea.is-invalid) { border-color: var(--danger); }

  :where(.form-control, .form-input) { width: 100%; }

  :where(.field-label, label) { display: inline-block; color: var(--ink); font-weight: 600; margin-bottom: .25rem; }

  @media (max-width: 480px) {
    :where(input:not([type="checkbox"]):not([type="radio"]):not([type="file"])),
    :where(select, textarea, .form-control, .form-input) { padding: 8px 10px; font-size: 0.95rem; }
  }

  /* ==========================================================================
     Search mark -- the searched word inside a page's own results, in the
     Search app's gold (copied from search/main.css). search-mark.js puts it
     there.
     ========================================================================== */
  .search-mark {
    background: #FFE24D;
    color: var(--ink);
    padding: 0 1px;
    border-radius: 2px;
  }

}

/* ==========================================================================
   House band -- the catalog manual page's heading: charcoal band, 2px ink
   edge, a 3px gold line along the bottom, gold eyebrow, gold count, gold +
   and gold chips, all in a 604px column. Twenty-six apps used to carry their
   own copy of it. These rules sit outside @layer base on purpose: they weigh
   exactly what those copies weighed, so an app's own rule (written after
   this file) still adds or overrides as before.
   ========================================================================== */
.stage {
    max-width: 604px;
    margin: 1.5rem auto 3rem;
    padding: 0 2px;
    color: var(--dark-surface);
}

.band {
    position: relative;
    background: var(--bg-footer);
    border: 2px solid var(--dark-surface);
    padding: 0.7rem 1rem 0.85rem;
    margin-bottom: 0.6rem;
}

.band::after {
    content: "";
    position: absolute;
    left: 0; right: 0; bottom: 0;
    height: 3px;
    background: var(--accent-gold);
}

/* the band as one row: eyebrow, name, count and + side by side */
.band--row {
    display: flex;
    align-items: center;
    gap: 0.75rem;
    margin-bottom: 1.1rem;
}

/* the row band stacked: rows under each other, full width */
.band--stack {
    flex-direction: column;
    align-items: stretch;
    gap: 6px;
}

/* staff pages: a wider band that sits flush on what follows */
.band--staff {
    padding: 0.7rem 1.25rem 0.85rem;
    margin-bottom: 0;
}

.band-eyebrow {
    font: 700 1rem/1 'Roboto', sans-serif;
    letter-spacing: 0.22em;
    text-transform: uppercase;
    color: var(--accent-gold);
}

.band-eyebrow--staff {
    font: 700 0.875rem/1 'Roboto', sans-serif;
    margin: 0;
}

.band-title {
    margin: 0;
    font: 400 1.6rem/1.05 'Roboto', sans-serif;
    color: #fff;
}

.band-headrow {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 0.6rem;
    margin-top: 0.35rem;
}

.band-count {
    margin-left: auto;
    font: 700 0.875rem/1.4 'Roboto', sans-serif;
    color: var(--bg-footer);
    background: var(--accent-gold);
    border: 1px solid var(--dark-surface);
    padding: 1px 7px;
    white-space: nowrap;
}

.band-add {
    font: 700 1.05rem/1 'Roboto', sans-serif;
    color: var(--bg-footer);
    background: var(--accent-gold);
    border: 2px solid var(--dark-surface);
    padding: 0.15rem 0.65rem;
    text-decoration: none;
    white-space: nowrap;
}

.band-chip {
    font: 700 0.875rem/1 'Roboto', sans-serif;
    letter-spacing: 0.08em;
    color: var(--bg-footer);
    background: var(--accent-gold);
    border: 2px solid var(--dark-surface);
    padding: 4px 10px;
    text-decoration: none;
    white-space: nowrap;
}

.band-chip--staff {
    padding: 6px 10px;
    text-transform: uppercase;
}

.band-chip--staff:hover {
    background: var(--gold-bright);
    color: var(--bg-footer);
}

.band-add:focus-visible,
.band-chip:focus-visible {
    outline: 3px solid var(--accent-teal-dark);
    outline-offset: 1px;
}

/* a white box for "nothing here yet" under the band */
.empty-box {
    background: var(--surface);
    border: 2px solid var(--dark-surface);
    padding: 2rem 1.25rem;
    text-align: center;
}

/* a white strip of filter chips under the band */
.filter-strip {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 0.35rem;
    background: var(--surface);
    border: 2px solid var(--dark-surface);
    padding: 0.45rem 0.5rem;
    margin-bottom: 0.6rem;
}

@media (max-width: 480px) {
    .stage { margin: 0.5rem auto 1.5rem; }
    .band { padding: 0.5rem 0.5rem 0.6rem; margin-bottom: 0.4rem; }
    .band--row { gap: 0.4rem; margin-bottom: 0.6rem; }
    .band--stack { gap: 4px; }
    .band--staff { padding: 0.5rem 2px 0.6rem; margin-bottom: 0; }
    .band-title { font-size: 1.3rem; }
    .band-headrow { gap: 0.35rem; }
    .empty-box { padding: 1.5rem 0.5rem; }
    .filter-strip { padding: 0.35rem 0.3rem; margin-bottom: 0.4rem; }
}
