/* KarateShowCase tenant — base-layout
 *
 * Generated by tools/consolidate-tenant-css.mjs from 44 source files,
 * concatenated in their original cascade order. Edit the sources, re-run the
 * tool; do not hand-edit this file.
 */

/* ══════════════════════════════════════════════════════════════════════
   dojo-global-table-scroll.v1.css
   ══════════════════════════════════════════════════════════════════════ */
/* Scroll region for tables wider than the space they are given.
 *
 * Paired with dojo-global-table-scroll.v1.js, which wraps each wide admin table
 * and makes the region focusable only while it actually scrolls. The styling
 * here is deliberately quiet: this is an affordance, not a component with a
 * look of its own, and it sits inside panels that already have their own
 * surface treatment. */

.ks-table-scroll {
  overflow-x: auto;
  overflow-y: visible;
  /* Momentum scrolling on touch, and a scrollbar that does not reserve space on
     platforms that overlay it. */
  -webkit-overflow-scrolling: touch;
  max-width: 100%;
}

/* The admin roster containers scroll only inside a max-width: 900px block in
   dojo-admin-light-theme-override.v1.css, so on a phone the last columns are
   reachable and on a desktop they are not. That is not a mobile concern: the
   users table is nine columns ending in Actions, and it exceeds its card
   whenever the text runs wider than it does here -- which is how CI caught it,
   clipped with nothing to scroll, on Linux at 1280px.
   Same treatment as the media block already applies, at every width. */
#view-admin #admin-users-table,
#view-admin #admin-tournaments-table,
#view-admin #admin-pending-approvals {
  overflow-x: auto;
  -webkit-overflow-scrolling: touch;
  width: 100%;
}

/* Focus has to be visible: the region is reachable by keyboard precisely when
   there is content off-screen, so a user who tabs to it needs to see that they
   have landed somewhere scrollable. */
.ks-table-scroll:focus-visible {
  outline: 2px solid var(--ks-focus-ring);
  outline-offset: 2px;
  border-radius: 8px;
}

/* A table given a scroll region should keep its own intrinsic width rather than
   being crushed to the container, or there would be nothing to scroll to. */
.ks-table-scroll>table {
  min-width: 100%;
}

@media (prefers-reduced-motion: reduce) {
  .ks-table-scroll {
    scroll-behavior: auto;
  }
}

/* ══ STACKED ROWS ON A PHONE ═══════════════════════════════════════════════
   Applied by dojo-global-table-scroll.v1.js, which adds .ks-table-stacked and
   labels every cell from the table's own <thead> below 760px. The breakpoint is
   named in both files; they must agree, because the labels are dead weight
   without these rules and these rules are unreadable without the labels.

   Why stacked rather than "scroll harder": a nine-column roster in 354px is
   reachable and unusable. Measured 2026-08-22, the actions menu that changes a
   belt or a membership status sat six columns past the right edge of a card
   whose scrollbar the stylesheet hides. A dojo owner on a phone could read the
   roster and not run it.

   Every selector is scoped to #view-admin, and that is specificity rather than
   tidiness: .upload-list-table carries `min-width: 600px` from
   dojo-admin-light-theme-override.v1.css, which loads AFTER this file, so an
   unscoped .ks-table-stacked would tie on weight and lose on order -- leaving
   600px-wide "cards" in a 365px column, which is the defect wearing a different
   shape.
   ═════════════════════════════════════════════════════════════════════════ */
@media (max-width: 760px) {

  #view-admin .ks-table-stacked {
    display: block;
    width: 100%;
    min-width: 0;
    border-collapse: collapse;
  }

  #view-admin .ks-table-stacked thead {
    /* The header text moves into the cells; keeping it here as well would read
       it twice to a screen reader. */
    display: none;
  }

  #view-admin .ks-table-stacked tbody,
  #view-admin .ks-table-stacked tr,
  #view-admin .ks-table-stacked td {
    width: auto;
  }

  #view-admin .ks-table-stacked tbody {
    display: block;
  }

  /* A definition grid, not a stack of full-width lines.
     Nine one-per-line fields made a card about 330px tall and eight of them a
     2,600px roster; the same nine in a two-up grid with the label above its
     value come to about 230px and read as a designed card rather than a list
     of dashes. auto-fill rather than a fixed two, so a narrow phone gets one
     column and a 700px tablet gets four without a second breakpoint.

     THE TRACK FLOOR IS THE WHOLE FIX, and the arithmetic is why: auto-fill
     fits a second track only when the row's content box holds two of them
     plus the column gap. At minmax(150px) with a .9rem gap that needed
     314.4px — and an iPhone gives this row 286px. So every iPhone width fell
     back to ONE column and printed all nine fields down the page: a member
     card measured 509px tall, taller than the screen it was on, which is the
     "big blocks" the owner reported. 412px — the Pixel 7 the phone project
     emulates — was just wide enough to fit two, so CI rendered the good case
     and never saw it. Measured 2026-08-28 at 320/360/375/390/412.

     118px + a .7rem gap needs 247.2px, which two columns clear on a 320px
     phone. The floor is min()-guarded so a container narrower than one track
     shrinks it rather than overflowing. */
  #view-admin .ks-table-stacked tr {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(min(100%, 118px), 1fr));
    gap: .42rem .7rem;
    align-items: start;
    background: var(--adm-surface, #fff);
    border: 1px solid var(--adm-line, #e4e7ec);
    border-radius: var(--adm-radius-sm, 10px);
    box-shadow: var(--adm-shadow-1, 0 1px 2px rgba(16, 24, 40, .05));
    padding: .7rem .8rem;
    margin: 0 0 .55rem;
  }

  #view-admin .ks-table-stacked tr:last-child {
    margin-bottom: 0;
  }

  /* TWO RECORDS PER SCREEN IS THE CONTRACT, and the height that stopped it
     was never the field count — it was the box around each pair.
     dojo-admin-light-theme-override sets `.admin-table td { padding: .5rem
     .4rem !important }` for the TABLE it was written for, and an !important
     declaration beats this file's higher-specificity one whatever its
     weight. That padding plus a .6rem flex gap put 25px of box around a
     label and a value: 44px per cell where the type needs 28. Four rows of
     that is where a 509px card came from, and why merely fixing the column
     count only brought it to 360px.

     So !important here on those two properties and only those two, which is
     the same fight the file's header documents for width. Measured
     2026-08-28: member card 509px → 272px, match card 416px → 262px, both
     two-up, with nothing hidden to get there — two records now read at once
     on a 375×812 phone. */
  #view-admin .ks-table-stacked td {
    display: flex;
    flex-direction: column;
    align-items: flex-start;
    gap: .04rem !important;
    padding: 0 !important;
    border: 0;
    text-align: left;
    font-size: .78rem;
    line-height: 1.2;
    /* An email address is one unbreakable token and these tracks are 150px. */
    overflow-wrap: anywhere;
    min-width: 0;
  }

  /* The column's name, printed where the header used to be. Only for cells that
     have one: a glyph column (the three-dot menu) resolves to an empty label in
     the script, and an empty ::before would still reserve its gap. */
  #view-admin .ks-table-stacked td[data-label]:not([data-label=""])::before {
    content: attr(data-label);
    font-family: 'Raleway', sans-serif;
    /* Was .55rem — 8.8px, small enough to read as noise above its own value.
       The shared primitive for this pair is .ks-kv in ks-app-surface, whose
       key sits at --ks-label; a table reflow cannot adopt that markup without
       rewriting the renderers, so it matches its treatment instead. */
    font-size: .64rem;
    font-weight: 800;
    letter-spacing: .1em;
    line-height: 1.15;
    text-transform: uppercase;
    color: var(--adm-ink-3, #5d6b82);
    white-space: nowrap;
  }

  /* The internal hairlines, removed with the specificity they were added
     with: #view-admin .admin-table td and its siblings set a border-bottom
     for the TABLE they were written for, and it survives into the card as a
     rule under every pair. The identity cell keeps its underline and the
     actions cell keeps its top rule — those two separate the card's parts,
     which is structure; the rest were a table drawn inside a card. */
  #view-admin .ks-table-stacked tbody tr td:not(:first-child):not(:last-child) {
    border-bottom: 0;
  }

  /* The first cell is the record's identity -- the avatar and the name, or the
     match's thumbnail -- so it is the card's heading: full width, no label of
     its own, with a rule under it. */
  #view-admin .ks-table-stacked td:first-child {
    grid-column: 1 / -1;
    padding: 0 0 .5rem !important;
    margin-bottom: .12rem;
    border-bottom: 1px solid var(--adm-line-soft, #f2f4f7);
    font-size: .86rem;
    font-weight: 600;
  }

  #view-admin .ks-table-stacked td:first-child[data-label]:not([data-label=""])::before {
    /* The heading names itself. The specificity has to match the label rule
       above -- an id and three compound parts -- or the reset loses to it. */
    content: none;
  }

  /* The actions cell closes the card on its own line, so the menu is a full
     tap target instead of a glyph wedged into a 150px track. */
  /* The actions cell closes the card on its own line — as ONE line. Stacked
     like every other cell it printed "ACTIONS" above a solitary three-dot
     button pinned to the far corner, which is two rows of card height spent
     on a glyph. Label and control share the row instead: the name is kept,
     the height is not. */
  #view-admin .ks-table-stacked td:last-child {
    grid-column: 1 / -1;
    flex-direction: row;
    align-items: center;
    justify-content: space-between;
    gap: .6rem;
    padding-top: .45rem !important;
    margin-top: .12rem;
    border-top: 1px solid var(--adm-line-soft, #f2f4f7);
  }

  /* Empty state, loading line, "couldn't load" -- one sentence spanning the
     table. The script marks them so they are not dressed up as a record. */
  #view-admin .ks-table-stacked td[data-stack-full] {
    grid-column: 1 / -1;
    display: block;
    text-align: center;
    /* !important to survive the cell reset above, which needs it to beat the
       admin override sheet — a sentence row still wants its breathing room. */
    padding: .4rem 0 !important;
    border: 0;
    margin: 0;
    font-weight: 400;
  }

  #view-admin .ks-table-stacked td[data-stack-full]::before {
    content: none;
  }

  /* Controls inside a cell keep their own alignment rather than being pulled
     to the right edge with the value text. */
  #view-admin .ks-table-stacked td .adm-actions-wrap,
  #view-admin .ks-table-stacked td .adm-user-cell {
    justify-content: flex-start;
  }

  /* A select or a button inside a cell should fill its track rather than
     shrink-wrapping to a stub beside its label. */
  #view-admin .ks-table-stacked td select,
  #view-admin .ks-table-stacked td .adm-role-select {
    max-width: 100%;
  }

  /* A control's TEXT is held at 16px platform-wide, because anything smaller
     magnifies the whole page on iOS — see ks-touch-control-sizing-responsive.
     That is not negotiable, so the height it costs is taken back from the
     padding around it instead: eight cards each carrying a role select is
     where a roster's length actually comes from. */
  #view-admin .ks-table-stacked td select {
    padding-block: 4px;
    line-height: 1.25;
  }

  /* The Overview roster caps itself at 440px and scrolls vertically, which was
     right for a dense table beside the uploads column. Stacked, eight members
     are about 1,100px, so the cap turns the card into a second scroll surface
     inside a page that already scrolls -- two nested scrollbars on a phone,
     and the outer one stops responding while a finger is inside the inner. The
     page is the scroller here.

     Keyed on the width, NOT on :has(.ks-table-stacked), and that is a
     correctness point rather than a style one. These containers are also what
     dojo-global-table-scroll.v1.js looks for when it needs something that
     scrolls: releasing overflow here makes the component insert its own wrapper
     instead, which breaks the :has() relationship, which restores the cap,
     which removes the wrapper. The condition and its consequence chased each
     other. The width is the real trigger and it cannot be moved by anything the
     component does. */
  #view-admin .dash-users-col .dash-users-scroll,
  #view-admin .dash-uploads-col .upload-list-scroll {
    max-height: none;
    /* BOTH axes, and both must actually win. `overflow: visible` on one axis
       computes to `auto` whenever the other axis is not visible, so leaving
       overflow-x to `#view-admin .dash-users-scroll { overflow-x: auto }` in
       dojo-admin-workspace.v1.css -- which ties this file on weight and loads
       after it -- turned overflow-y back into a scroller. Measured as
       overflow-y: auto with max-height already released. The extra class in
       each selector is what settles that, rather than a bundle-order pin. */
    overflow-x: visible;
    overflow-y: visible;
  }

  /* The uploads card leads with a thumbnail rather than a name, so its heading
     cell holds an image and needs the room to show one. */
  #view-admin .ks-table-stacked td:first-child img {
    /* The uploads card leads with a thumbnail. Full-width would make a 412px
       hero out of a 72px cell. */
    max-width: 128px;
    height: auto;
    border-radius: 8px;
  }

  /* ── A MEDIA LIST READS AS ONE ────────────────────────────────────────────
     A match is a picture and a name, and the generic card gives its first
     cell a full-width heading row — which for the uploads table meant a lone
     thumbnail on one line with the competitor's name stranded below it under
     its own label. Marked in the markup with [data-ks-media-list] rather than
     inferred from the table's class, because #dash-users-table shares that
     class and leads with a person, not a picture.

     Here the thumbnail takes one track and the name sits beside it, so the
     row opens the way a video list opens everywhere else in the product. */
  #view-admin table[data-ks-media-list].ks-table-stacked td:first-child {
    grid-column: span 1;
    padding: 0;
    margin: 0;
    border-bottom: 0;
  }

  #view-admin table[data-ks-media-list].ks-table-stacked td:first-child img,
  #view-admin table[data-ks-media-list].ks-table-stacked td:first-child .upload-thumb,
  #view-admin table[data-ks-media-list].ks-table-stacked td:first-child .upload-thumb-empty {
    width: 100%;
    max-width: 100%;
    height: auto;
    aspect-ratio: 16 / 10;
    object-fit: cover;
  }

  /* The name is the card's heading now, so it carries the heading's weight —
     and its own rule, because the identity is the SECOND cell here. */
  #view-admin table[data-ks-media-list].ks-table-stacked td:nth-child(2) {
    align-self: center;
    font-size: .86rem;
    font-weight: 600;
  }

  /* A button that already says what it does does not need the column's name
     printed beside it: the closing row read "WATCH        [ WATCH ]". */
  #view-admin table[data-ks-media-list].ks-table-stacked td:last-child {
    justify-content: flex-end;
  }

  #view-admin table[data-ks-media-list].ks-table-stacked td:last-child::before {
    content: none;
  }

  /* Zebra striping belongs to a table, where it tells one ROW from the next.
     Once each row is its own bordered card the stripe lands on the cells
     inside it instead, and a card reads as a patchwork of grey blocks. The
     card is the surface here. */
  #view-admin .ks-table-stacked tbody tr td {
    background: transparent;
  }
}


/* ══════════════════════════════════════════════════════════════════════
   dojo-global-foundation-reset-tokens.v1.css
   ══════════════════════════════════════════════════════════════════════ */
    /* Legacy compatibility layer.
     *
     * What is left here is what still has readers. 55 declarations were removed
     * because nothing in the repository read them — the whole --space-* scale,
     * the --leading-* scale, --surface-0..3, the gold composites, and the
     * --color-* aliases. They were the shape of a design system that the
     * --ks-* layers replaced; keeping them meant every reader had two names for
     * the same idea and no way to tell which was current.
     *
     * The rest is not dead and is not removed:
     *   --gold, --gold-lt   REMOVED. They looked live because the kumite clock,
     *                       the legal shells and the marketing homepage all read
     *                       a token of that name — but each of those pages
     *                       declares its OWN, and none of them loads this file.
     *                       Only the tenant page does, and its last functional
     *                       reader went with the tenant JavaScript. Verified by
     *                       resolving what dist/homann/index.html actually loads
     *                       and scanning only those files.
     *   --blue --navy --bg  the marketing homepage's own palette.
     *   --white --text      still read across the tenant cascade and the legal
     *   --muted --dim       shells; a rename with no behaviour change is churn.
     *   scales and z-index  --radius-*, --duration-*, --ease-out, --z-* have
     *                       live readers on migrated surfaces.
     *
     * Verified empty by scanning every .css/.js/.mjs/.html/.ts in the repo for
     * var(--name), plus getPropertyValue() for dynamic reads.
     */
    *,
    *::before,
    *::after {
      box-sizing: border-box;
      margin: 0;
      padding: 0
    }

    :root {
      /* ── EXISTING PALETTE ─────────────────────────────────── */
      --bg: #050A14;
      --dojo-accent: #D4AF37;
      --navy: #0A1324;
      --mid: #121F36;
      --lite: #1A2942;
      --white: #FFFFFF;
      --text: #E0DCD2;
      --muted: #9EADC6;
      --dim: #5A6E8A;
      /* --danger removed: it shadowed the platform layer from a bundle that
         loads later, and nothing held it to a contrast threshold. The danger
         role is --ks-danger in the theme layer, which is theme-aware and
         checked by verify-theme-token-contrast.mjs. */
      --success: #3CB371;
      --blue: #3498db;
      --border-dim: 1px solid rgba(255, 255, 255, 0.07);

      /* ── 1. SPACING SCALE (4px base, ~1.5× progression) ─── */

      /* ── 2. TYPOGRAPHY SCALE ────────────────────────────── */
      --text-sm: .72rem;
      --text-base: .85rem;
      --text-md: 1rem;
      --text-xl: 1.35rem;
      --text-2xl: 1.6rem;
      --leading-2xl: 1.25;

      /* ── 3. BORDER RADIUS SCALE ─────────────────────────── */
      --radius-sm: 4px;
      --radius-md: 8px;
      --radius-lg: 14px;
      --radius-full: 9999px;

      /* ── 4. SHADOW SCALE ────────────────────────────────── */
      --shadow-sm: 0 1px 3px rgba(0, 0, 0, 0.25);
      --shadow-xl: 0 16px 48px rgba(0, 0, 0, 0.55);

      /* ── 5. Z-INDEX SCALE ───────────────────────────────── */
      --z-sticky: 200;
      --z-overlay: 300;
      --z-modal: 400;
      --z-toast: 500;

      /* ── 6. MOTION TOKENS ───────────────────────────────── */
      --ease-out: cubic-bezier(0.165, 0.84, 0.44, 1);
      --duration-fast: 150ms;
      --duration-base: 250ms;

      /* ── 7. SURFACE TOKENS ──────────────────────────────── */

      /* ── 8. SEMANTIC COLOR TOKENS ───────────────────────── */
    }

/* ── A failed image must never render as a broken image ──────────────────────
 *
 * An <img> with no src attribute is not an invisible element — every browser
 * draws its broken-image icon and alt text in the element's box. On 2026-08-14
 * that was the homann header: the tenant logo's gateway request failed, the
 * media runtime removed the src exactly as designed, and the result was a
 * broken icon at full opacity in the first thing a visitor sees.
 *
 * data-media-state had been published for this since the media cutover, but
 * hiding on it was opt-in and only four surfaces had opted in. This makes it
 * the default for every image on the platform; the per-surface rules that
 * already exist stay valid and simply become redundant.
 *
 * 'fallback' is deliberately NOT hidden — it means the element is showing the
 * platform mark from data-default-src, which is a real image and should show. */
img[data-media-state="empty"],
img[data-media-state="error"] {
  opacity: 0;
  /* Not display:none — these images are usually inside a sized slot whose
   * layout should stay stable while media resolves, and collapsing it would
   * make the page jump on every tenant that has not filled a slot. */
  pointer-events: none;
}


/* ══════════════════════════════════════════════════════════════════════
   dojo-global-document-view-shell.v1.css
   ══════════════════════════════════════════════════════════════════════ */
    html {
      background: var(--bg);
      overflow-x: hidden;
      /* Mobile browsers inflate text on their own. Chromium's autosizer and
         WebKit's text-size-adjust both grow type inside a block past the size
         the stylesheet asked for, keyed on how much text that block holds — so
         the same card renders one size on a phone and another once its content
         changes, with nothing in this repository requesting either.
         That is not a cosmetic difference. Every intrinsic width is computed
         from the rendered type, so inflated text widens a grid track's
         min-content, and a track that cannot shrink below it carries its card
         off the side of the screen. Found 2026-08-28: the home command centre's
         cards were clipped past the right edge of a 412px viewport on Linux CI
         and nowhere else, on markup and CSS byte-identical to a passing tree.
         The declaration below is the reset that was never here. Type is the
         size it is declared to be, and phones stop being a second, invisible
         set of font sizes. */
      -webkit-text-size-adjust: 100%;
      text-size-adjust: 100%
    }

    /* A sticky footer, which is also what stops a short page carrying a screen
       of empty canvas.
       ─────────────────────────────────────────────────────────────────────────
       Several views carried `min-height: 100vh` so the canvas would reach the
       bottom of the window when their content did not. It reaches, but the
       footer is a sibling *after* the view, so the page became a full viewport
       of view plus a footer below it -- and on any page shorter than the screen
       the difference showed as dead canvas between the last card and the
       footer. Five hundred pixels of nothing on a competitor's own profile.

       Flexing the column gives the same guarantee with none of that: the active
       view grows to fill whatever the footer does not use, and stops.

       Safe because only two things are ever in this flow -- the one view with
       `.active`, and the footer. Everything else in <body> is fixed (the nav,
       the dock, the overlays, the lifecycle shell, the toast) or a <script>. */
    body {
      background: var(--bg);
      color: var(--text);
      font-family: 'Raleway', sans-serif;
      display: flex;
      flex-direction: column;
      min-height: 100vh;
      overflow-x: hidden;
      background-image:
        radial-gradient(ellipse at 50% 0%, color-mix(in oklab, var(--accent) 8%, transparent) 0%, transparent 60%),
        radial-gradient(ellipse at 50% 100%, rgba(10, 19, 36, 0.85) 0%, transparent 40%);
    }

    /* ── VIEW SWITCHING ─────────────────────────────────────────────────────── */
    .view {
      display: none;
      contain: content
    }

    .view.active {
      display: block;
      padding-top: 72px;
      contain: none;
      /* Grows into the space, never shrinks out of it. `1 0 auto` rather than
         `1`, because `flex: 1` sets flex-basis 0 and a long page would then be
         laid out from nothing and lose its own height. */
      flex: 1 0 auto;
    }

    /* A view that OPENS with a full-bleed band pays no nav allowance here:
       the band was built to run underneath the fixed nav and its own padding
       already begins with var(--ks-nav-h) (see .ks-hero and .ks-pagehead).
       Before this rule both paid, and every band-led view carried 72px of
       dead dark canvas between the nav and its first line — the "red box"
       measured on the homann hero 2026-08-15: 192px above the headline
       against 64px below the actions. Views that open with ordinary content
       (admin, detail pages) keep the allowance above. */
    .view.active:has(> .ks-band:first-child) {
      padding-top: 0;
    }

    body > .site-footer {
      flex: 0 0 auto;
    }


/* ══════════════════════════════════════════════════════════════════════
   dojo-global-command-dock-auth-mobile-shell.v1.css
   ══════════════════════════════════════════════════════════════════════ */
    /* ── Nav Right (login/profile) ─────────────────────────────────────────── */
    .nav-right {
      display: flex;
      align-items: center;
      gap: .75rem;
      flex-shrink: 0
    }

    .nav-right>.btn {
      background: none !important;
      border: none !important;
      color: rgba(255, 255, 255, 0.5) !important;
      font-size: .65rem !important;
      font-weight: 700 !important;
      letter-spacing: 1.2px !important;
      text-transform: uppercase !important;
      padding: 6px 12px !important;
      cursor: pointer;
      border-radius: 20px !important;
      box-shadow: none !important;
      backdrop-filter: none !important;
      transition: color .2s ease, background .2s ease
    }

    .nav-right>.btn:hover {
      color: var(--accent-on-inverse) !important;
      background: color-mix(in oklab, var(--accent) 14%, transparent) !important;
      border: none !important;
      transform: none !important;
      box-shadow: none !important
    }

    .nav-right>.btn::after {
      display: none
    }

    /* ── Mobile Pill Close Button (hidden on desktop) ──────────────────────── */
    .nav-pill-close {
      display: none !important
    }

    /* ── Mobile Menu Overlay ───────────────────────────────────────────────── */
    .mobile-menu-overlay {
      position: fixed;
      top: 0;
      left: 0;
      right: 0;
      bottom: 0;
      z-index: 150;
      background: rgba(0, 0, 0, 0.6);
      opacity: 0;
      visibility: hidden;
      transition: opacity .25s ease, visibility .25s ease;
      pointer-events: none
    }

    .mobile-menu-overlay.open {
      opacity: 1;
      visibility: visible;
      pointer-events: auto
    }

    /* ── Mobile Bottom Dock (hidden on desktop) ────────────────────────────── */
    .mobile-dock {
      display: none
    }

    .mobile-auth-item {
      display: none !important
    }

    .auth-hidden {
      display: none !important
    }


/* ══════════════════════════════════════════════════════════════════════
   dojo-global-home-light-action-shell.v1.css
   ══════════════════════════════════════════════════════════════════════ */
    /* ── HOME LIGHT SECTION ─────────────────────────────────────────────────── */
    .home-light-section {
      background: #F4F6FB;
      display: flex;
      flex-direction: column;
      align-items: center;
      padding: 0 1.5rem 0
    }

    /* ── HOME ACTION CARDS ───────────────────────────────────────────────────── */
    .home-action-grid {
      width: 100%;
      max-width: 920px;
      display: grid;
      grid-template-columns: repeat(3, minmax(0, 1fr));
      gap: 1rem;
      margin-bottom: 1rem;
      align-items: stretch
    }

    /* Banner sits below all 3 cards on desktop */
    #home-special-banner {
      order: 10
    }

    /* Schedule is inside More dropdown — display managed by .dock-more-dropdown li */

    .home-action-card {
      background: linear-gradient(180deg, rgba(15, 23, 42, 0.85) 0%, rgba(30, 41, 59, 0.95) 100%);
      border: 1px solid color-mix(in oklab, var(--accent) 20%, transparent);
      border-radius: 14px;
      padding: .9rem .9rem .85rem;
      text-align: left;
      box-shadow: 0 8px 30px rgba(0, 0, 0, 0.3), inset 0 1px 2px rgba(255, 255, 255, 0.05);
      backdrop-filter: blur(16px);
      -webkit-backdrop-filter: blur(16px);
      display: flex;
      flex-direction: column;
      gap: .5rem;
      min-height: 228px;
      justify-content: flex-start;
      height: 100%;
      transition: transform .4s cubic-bezier(0.165, 0.84, 0.44, 1), box-shadow .4s, border-color .4s;
    }

    .home-action-card:hover {
      transform: translateY(-4px);
      box-shadow: 0 16px 40px rgba(0, 0, 0, 0.5), 0 0 20px color-mix(in oklab, var(--accent) 10%, transparent);
      border-color: color-mix(in oklab, var(--accent) 40%, transparent);
    }

    .home-action-eyebrow {
      font-size: .75rem;
      font-weight: 900;
      letter-spacing: 2.4px;
      text-transform: uppercase;
      color: var(--ks-accent-strong)
    }

    .home-action-title {
      font-family: var(--ks-display);
      font-size: 1.3rem;
      color: #FFF;
      line-height: 1.2;
      font-weight: 900
    }

    .home-action-copy {
      font-size: 1rem;
      color: #E2E8F0;
      line-height: 1.6;
      font-weight: 700
    }

    .home-action-card .btn {
      align-self: flex-start;
      margin-top: auto
    }

    .home-action-card:not(.calendar-card) {
      text-align: center;
      align-items: center;
      justify-content: center;
      padding: 1.05rem 1rem
    }

    .home-action-card:not(.calendar-card) .home-action-eyebrow {
      font-size: .8rem;
      letter-spacing: 2.8px
    }

    .home-action-card:not(.calendar-card) .home-action-title {
      font-size: 1.4rem;
      max-width: 240px
    }

    .home-action-card:not(.calendar-card) .home-action-copy {
      font-size: 1.05rem;
      line-height: 1.65;
      max-width: 260px
    }

    .home-action-card:not(.calendar-card) .btn {
      align-self: center;
      margin-top: auto
    }


/* ══════════════════════════════════════════════════════════════════════
   dojo-global-command-center-layout.v1.css
   ══════════════════════════════════════════════════════════════════════ */
    /* ── COMMAND CENTER LAYOUT ─────────────────────────────────────────────── */
    .cc-wrap {
      width: 100%;
      max-width: 1060px;
      margin: 0 auto;
      display: flex;
      flex-direction: column;
      gap: 1.5rem;
    }

    /* Two cards — Next Up and Team Calendar. See dojo-home-shell.v2.css for why
       the third went and why this is `start` rather than `stretch`. */
    .cc-top-row {
      display: grid;
      grid-template-columns: minmax(0, 1fr) minmax(0, 1.15fr);
      gap: 1.25rem;
      align-items: start;
    }


/* ══════════════════════════════════════════════════════════════════════
   dojo-home-command-center-card-shell.v1.css
   ══════════════════════════════════════════════════════════════════════ */
    .cc-card {
      background: #FFFFFF;
      border: 1px solid rgba(26, 41, 66, 0.1);
      border-radius: 14px;
      padding: 1.25rem;
      display: flex;
      flex-direction: column;
      box-shadow: 0 2px 8px rgba(10, 19, 36, 0.06), 0 1px 3px rgba(10, 19, 36, 0.04);
      transition: box-shadow .35s cubic-bezier(.4, 0, .2, 1), transform .35s cubic-bezier(.4, 0, .2, 1), border-color .35s ease;
      min-height: 0;
    }

    .cc-card:hover {
      transform: translateY(-4px);
      box-shadow: 0 10px 32px rgba(10, 19, 36, 0.12), 0 2px 8px rgba(10, 19, 36, 0.06), 0 0 0 1px color-mix(in oklab, var(--accent) 15%, transparent);
      border-color: color-mix(in oklab, var(--accent) 20%, transparent);
    }

    .cc-card-header {
      display: flex;
      align-items: center;
      justify-content: center;
      text-align: center;
      gap: .5rem;
      margin-bottom: .85rem;
      padding-bottom: .6rem;
      border-bottom: 2px solid rgba(10, 19, 36, 0.08);
    }

    .cc-card-header-icon {
      font-size: 1.3rem;
      color: var(--ks-accent-strong);
    }

    .cc-card-header-title {
      font-family: var(--ks-display);
      font-size: 1.25rem;
      font-weight: 900;
      color: #0A1324;
      letter-spacing: 2px;
      text-transform: uppercase;
    }


/* ══════════════════════════════════════════════════════════════════════
   dojo-home-command-center-button-base.v1.css
   ══════════════════════════════════════════════════════════════════════ */
    .cc-btn {
      font-family: 'Raleway', sans-serif;
      font-size: .72rem;
      font-weight: 900;
      letter-spacing: 1.5px;
      text-transform: uppercase;
      padding: 9px 18px;
      border-radius: var(--ks-r-control-sm);
      cursor: pointer;
      /* Named properties rather than `all`, which also covers outline-width and
         outline-offset and would fade a keyboard focus ring in over a quarter
         second. The same fix as .premium-btn (f499c12) and .btn (46b1582), and
         the last of the three button systems.

         Measured before changing it: this declaration is currently shadowed
         everywhere it is used. Every .cc-btn in the product carries a variant,
         .cc-btn-gold and .cc-btn-outline both name their own properties later in
         the cascade at equal specificity, and `#view-home .cc-btn` outranks all
         of them anyway. The one combination that did resolve to `all` was a bare
         .cc-btn outside #view-home, which nothing emits. So this is closing a
         trap rather than a live defect: the first bare .cc-btn anyone writes, or
         the first use of these classes off the home view, would have animated
         its ring with nothing to catch it.

         The list is the union of what the variants actually move --
         transform/box-shadow/filter from .cc-btn-gold's hover and active,
         border-color/color/background from .cc-btn-outline's hover, and
         background/border-color/color from the #view-home overrides. No opacity:
         unlike the .btn system there is no disabled state on these. */
      transition-property: background, border-color, color, box-shadow, transform, filter;
      transition-duration: .25s;
      transition-timing-function: ease;
      white-space: nowrap;
      text-decoration: none;
      display: inline-flex;
      align-items: center;
      gap: 4px;
    }

    .cc-btn-gold {
      background: linear-gradient(135deg, var(--ks-accent) 0%, var(--ks-accent) 100%);
      color: var(--ks-on-accent);
      border: 1px solid color-mix(in oklab, var(--accent) 40%, transparent);
      box-shadow: 0 1px 4px color-mix(in oklab, var(--accent) 20%, transparent);
    }

    .cc-btn-gold:hover {
      transform: translateY(-1px);
      box-shadow: 0 3px 12px color-mix(in oklab, var(--accent) 35%, transparent);
      filter: brightness(1.05);
    }

    .cc-btn-outline {
      background: transparent;
      color: #1A2942;
      border: 1px solid #C9D1DC;
    }

    .cc-btn-outline:hover {
      border-color: var(--ks-accent);
      color: var(--ks-accent-strong);
      background: color-mix(in oklab, var(--accent) 6%, transparent);
    }


/* ══════════════════════════════════════════════════════════════════════
   dojo-home-command-center-card-shell-dark.v1.css
   ══════════════════════════════════════════════════════════════════════ */
    /* ── Main cards: Next Event, Calendar, Quick Links ──────────────────── */
    .cc-card {
      background: linear-gradient(160deg, #0C1628 0%, #122040 50%, #0E1830 100%);
      border: 1px solid color-mix(in oklab, var(--accent) 18%, transparent);
      box-shadow: 0 4px 24px rgba(0, 0, 0, 0.35), inset 0 1px 0 color-mix(in oklab, var(--accent) 6%, transparent);
    }

    .cc-card:hover {
      border-color: color-mix(in oklab, var(--accent) 35%, transparent);
      box-shadow: 0 12px 40px rgba(0, 0, 0, 0.45), 0 0 20px color-mix(in oklab, var(--accent) 8%, transparent), inset 0 1px 0 color-mix(in oklab, var(--accent) 8%, transparent);
    }

    .cc-card-header {
      border-bottom: 2px solid color-mix(in oklab, var(--accent) 15%, transparent);
    }

    .cc-card-header-title {
      color: #FFFFFF;
    }


/* ══════════════════════════════════════════════════════════════════════
   dojo-home-special-banner-base.v1.css
   ══════════════════════════════════════════════════════════════════════ */
    .home-special-banner {
      display: none;
      margin: 0 auto 2rem;
      max-width: 600px;
      width: 100%;
      background: linear-gradient(135deg, rgba(52, 152, 219, 0.15) 0%, #0F172A 65%);
      border: 1px solid rgba(93, 173, 226, 0.35);
      border-top: 2px solid rgba(93, 173, 226, 0.5);
      border-radius: 16px;
      padding: 1.1rem 1.4rem;
      text-align: center;
      box-shadow: 0 8px 30px rgba(0, 0, 0, 0.2);
      position: relative;
      overflow: hidden
    }

    .home-special-banner::before {
      content: '';
      position: absolute;
      top: 0;
      left: 0;
      right: 0;
      height: 2px;
      background: linear-gradient(90deg, rgba(93, 173, 226, 0.8), color-mix(in oklab, var(--accent) 60%, transparent), transparent)
    }

    .home-special-banner.show {
      display: flex;
      flex-direction: column;
      align-items: center;
      justify-content: center;
      gap: .55rem;
      animation: bannerIn .35s cubic-bezier(0.165, 0.84, 0.44, 1) both
    }

    @keyframes bannerIn {
      from {
        opacity: 0;
        transform: translateY(-8px)
      }

      to {
        opacity: 1;
        transform: translateY(0)
      }
    }

    .home-special-kicker {
      font-size: .95rem;
      font-weight: 900;
      letter-spacing: 4px;
      text-transform: uppercase;
      color: var(--ks-accent-strong);
      margin-bottom: .35rem;
      display: flex;
      align-items: center;
      justify-content: center;
      gap: .5rem;
      text-shadow: 0 0 12px color-mix(in oklab, var(--accent) 40%, transparent)
    }

    .home-special-kicker::before {
      content: '◆';
      font-size: .45rem;
      color: var(--ks-accent-strong);
      animation: pulse 1.4s ease-in-out infinite
    }

    @keyframes pulse {

      0%,
      100% {
        opacity: 1
      }

      50% {
        opacity: .3
      }
    }

    .home-special-title {
      font-family: var(--ks-display);
      font-size: 1.35rem;
      color: #FFF;
      line-height: 1.25;
      margin-bottom: .15rem;
      font-weight: 900
    }

    .home-special-meta {
      font-size: .95rem;
      color: #D7E6F8;
      line-height: 1.6;
      font-weight: 700
    }

    .home-special-list {
      display: flex;
      flex-direction: column;
      gap: .4rem;
      margin-top: .25rem;
      width: 100%
    }

    .home-special-list-item {
      font-size: .95rem;
      color: #D7E6F8;
      line-height: 1.55;
      font-weight: 700;
      padding: .35rem .65rem;
      border-radius: 6px;
      background: rgba(255, 255, 255, 0.06);
      border-left: 2px solid rgba(93, 173, 226, 0.5);
      text-align: left
    }

    .home-special-list-item strong {
      color: #FFF;
      display: block;
      margin-bottom: .1rem;
      font-weight: 900
    }

    .home-special-banner .btn {
      flex-shrink: 0;
      margin-top: .25rem
    }


/* ══════════════════════════════════════════════════════════════════════
   dojo-page-header-search-shell.v1.css
   ══════════════════════════════════════════════════════════════════════ */
    /* ── PAGE HEADERS ────────────────────────────────────────────────────────── */
    .page-hdr {
      padding: 1.8rem 1.5rem .9rem;
      background: var(--bg)
    }

    .page-hdr h2 {
      font-family: var(--ks-display);
      font-size: 1.2rem;
      letter-spacing: 4.5px;
      color: var(--white);
      margin-bottom: .25rem;
      font-weight: 700
    }

    .page-hdr p {
      font-size: .68rem;
      color: var(--muted);
      letter-spacing: .5px
    }

    /* ── SEARCH BAR ──────────────────────────────────────────────────────────── */
    .search-wrap {
      position: relative;
      margin: 0 1.5rem 1.5rem
    }

    .search-wrap input {
      width: 100%;
      background: rgba(255, 255, 255, 0.04);
      border: 1px solid rgba(255, 255, 255, 0.1);
      border-radius: var(--ks-r-control-sm);
      padding: 12px 16px 12px 42px;
      color: var(--white);
      font-family: 'Raleway', sans-serif;
      font-size: .9rem;
      transition: border-color .2s;
      letter-spacing: .5px
    }

    .search-wrap input:focus {
      outline: none;
      border-color: color-mix(in oklab, var(--accent) 50%, transparent);
      background: rgba(255, 255, 255, 0.06)
    }

    .search-wrap input::placeholder {
      color: var(--dim)
    }

    .si {
      position: absolute;
      left: 14px;
      top: 50%;
      transform: translateY(-50%);
      color: var(--dim);
      font-size: .95rem;
      pointer-events: none
    }


/* ══════════════════════════════════════════════════════════════════════
   dojo-fighters-grid-shell.v1.css
   ══════════════════════════════════════════════════════════════════════ */
    /* ── FIGHTERS GRID ───────────────────────────────────────────────────────── */
    .fighters-wrap {
      padding: 0 1rem 4rem;
      max-width: 860px;
      margin: 0 auto
    }

    .grid {
      display: grid;
      grid-template-columns: 1fr 1fr;
      gap: .75rem
    }


/* ══════════════════════════════════════════════════════════════════════
   dojo-fighter-belt-bar-base.v1.css
   ══════════════════════════════════════════════════════════════════════ */
    .belt-bar {
      width: 10px;
      height: 100%;
      position: absolute;
      left: 0;
      top: 0;
      z-index: 2;
      border-right: 1px solid rgba(255, 255, 255, 0.08);
      transition: box-shadow .2s ease;
    }

    .belt-bar::after {
      content: '';
      position: absolute;
      inset: 0;
      background: linear-gradient(180deg, rgba(255, 255, 255, 0.28) 0%, rgba(255, 255, 255, 0.06) 25%, transparent 55%, rgba(0, 0, 0, 0.18) 100%);
      pointer-events: none;
      z-index: 1;
    }


/* ══════════════════════════════════════════════════════════════════════
   dojo-admin-light-theme-override.v1.css
   ══════════════════════════════════════════════════════════════════════ */
    /* ── ADMIN: LIGHT THEME OVERRIDE ────────────────────────────────────────── */
    #view-admin {
      background: var(--ks-canvas);
      color: var(--ks-ink);
      min-height: 100vh
    }

    /* ── ADMIN TOP HEADER BAR (dark navy strip) ─────────────────────────────── */
    /* THE BAND NAMES, NOT THE THEME NAMES, AND THAT IS THE WHOLE POINT HERE.
       This strip is dark in both themes, so --ks-ink and friends are the wrong
       vocabulary for anything inside it: on a light page they resolve to near
       black and would paint dark text on a navy bar. --ks-band-* is declared
       outside the light/dark pair precisely because it is brand rather than
       theme, and its ink steps are held to 4.5:1 against --ks-band. The shadow
       stays a literal: --ks-shadow-* is tuned for a light surface and reads as
       dirt under a dark bar. */
    .admin-topbar {
      display: flex;
      align-items: center;
      justify-content: space-between;
      gap: 1rem;
      padding: 1rem 2rem;
      background: var(--ks-band);
      position: sticky;
      top: 0;
      z-index: 50;
      box-shadow: 0 2px 12px rgba(0, 0, 0, 0.18)
    }

    .admin-topbar-brand {
      display: flex;
      align-items: center;
      gap: 10px
    }

    .admin-topbar-brand img {
      width: 34px;
      height: 34px;
      border-radius: 8px;
      object-fit: contain
    }

    .admin-topbar-brand-title {
      font-family: var(--ks-display);
      font-size: .72rem;
      font-weight: 700;
      letter-spacing: 2px;
      color: var(--ks-band-ink);
      text-transform: uppercase;
      line-height: 1.1
    }

    .admin-topbar-brand-sub {
      font-size: .48rem;
      letter-spacing: 1.5px;
      color: var(--ks-accent-strong);
      text-transform: uppercase;
      margin-top: 1px;
      font-weight: 600
    }

    .admin-topbar-search {
      flex: 1;
      max-width: 380px;
      position: relative;
      margin: 0 1.5rem
    }

    .admin-topbar-search input {
      width: 100%;
      padding: 8px 14px 8px 34px;
      border-radius: var(--ks-r-control);
      background: rgba(255, 255, 255, 0.08);
      border: 1px solid var(--ks-band-line);
      color: var(--ks-band-ink);
      font-size: .75rem;
      font-family: 'Raleway', sans-serif;
      transition: border-color .2s
    }

    .admin-topbar-search input:focus {
      outline: none;
      border-color: color-mix(in oklab, var(--accent) 40%, transparent)
    }

    /* The tertiary band ink rather than 35% white: the token is the quietest
       step held to 4.5:1 on the band, and a placeholder is exactly the tertiary
       role. The old wash composited to roughly 3:1 and failed at this size. */
    .admin-topbar-search input::placeholder {
      color: var(--ks-band-ink-3)
    }

    /* The magnifier is sprite markup in the field now (.admin-search-icon in
       dojo-admin-workspace.v1.css) — an emoji ::before could not answer to the
       icon language or the theme. */
    .admin-topbar-search::before {
      content: none
    }

    /* .admin-topbar-actions, .admin-add-btn and .admin-topbar-avatar were
       styled here for markup that no longer exists anywhere — the JS that
       wrote the avatar's initials targeted an element no page renders.
       Deleted with that write, 2026-08-16. */

    /* ── WELCOME / HEADER ──────────────────────────────────────────────────── */
    .admin-welcome {
      padding: 1.5rem 2rem 1.25rem;
      background: var(--ks-surface);
      position: relative;
      border-bottom: 1px solid var(--ks-line)
    }

    .admin-welcome h2 {
      font-family: var(--ks-display);
      font-size: 1.35rem;
      color: var(--ks-ink);
      margin-bottom: .3rem;
      letter-spacing: 1px
    }

    .admin-welcome p {
      font-size: .78rem;
      color: var(--ks-ink-3);
      letter-spacing: .5px
    }

    /* ── STATS CARDS ───────────────────────────────────────────────────────── */
    .admin-stats {
      display: grid;
      grid-template-columns: repeat(4, 1fr);
      gap: 1rem;
      padding: 1.25rem 2rem 1.5rem;
      background: var(--ks-canvas)
    }

    .admin-stat-card {
      background: var(--ks-surface);
      border: 1px solid var(--ks-line);
      border-radius: 14px;
      padding: 1.1rem 1.25rem;
      position: relative;
      overflow: hidden;
      box-shadow: 0 1px 4px rgba(0, 0, 0, 0.06), 0 1px 2px rgba(0, 0, 0, 0.04);
      transition: transform .2s ease, box-shadow .2s ease;
      border-left: 3px solid var(--ks-accent)
    }

    .admin-stat-card:hover {
      transform: translateY(-2px);
      box-shadow: 0 6px 20px rgba(0, 0, 0, 0.08);
      background: var(--ks-surface)
    }

    .admin-stat-icon {
      width: 40px;
      height: 40px;
      border-radius: 10px;
      display: flex;
      align-items: center;
      justify-content: center;
      font-size: 1.1rem;
      margin-bottom: .6rem;
      background: color-mix(in oklab, var(--accent) 10%, transparent);
      color: var(--ks-accent-strong)
    }

    .admin-stat-label {
      font-size: .52rem;
      letter-spacing: 2.5px;
      text-transform: uppercase;
      color: var(--ks-ink-3);
      margin-bottom: .2rem;
      font-weight: 700
    }

    .admin-stat-val {
      font-family: var(--ks-display);
      font-size: 1.6rem;
      font-weight: 700;
      color: var(--ks-ink);
      line-height: 1
    }

    .admin-stat-sub {
      font-size: .57rem;
      color: var(--ks-accent-strong);
      margin-top: .3rem;
      font-weight: 600
    }

    /* ── TAB NAVIGATION ────────────────────────────────────────────────────── */
    .admin-tabs {
      display: flex;
      gap: 0;
      padding: 0 2rem;
      background: var(--ks-surface);
      border-bottom: 2px solid var(--ks-line)
    }

    .admin-tab {
      padding: 13px 22px;
      text-align: center;
      cursor: pointer;
      position: relative;
      font-size: .7rem;
      font-weight: 700;
      letter-spacing: 2px;
      text-transform: uppercase;
      color: var(--ks-ink-3);
      transition: all .2s ease;
      border-bottom: 2px solid transparent;
      margin-bottom: -2px
    }

    .admin-tab:hover {
      color: var(--ks-ink)
    }

    .admin-tab.active {
      color: var(--ks-accent-strong);
      border-bottom-color: var(--ks-accent)
    }

    .admin-tab-content {
      display: none
    }

    .admin-tab-content.active {
      display: block
    }

    /* ── ADMIN SECTION (cards on light bg) ─────────────────────────────────── */
    .admin-section {
      background: var(--ks-surface);
      border: 1px solid var(--ks-line);
      border-radius: 14px;
      padding: 1.5rem;
      margin: 1.25rem 2rem;
      box-shadow: 0 1px 4px rgba(0, 0, 0, 0.06), 0 1px 2px rgba(0, 0, 0, 0.03)
    }

    .admin-section-title {
      font-family: var(--ks-display);
      font-size: .8rem;
      letter-spacing: 3px;
      color: var(--ks-ink);
      margin-bottom: 1rem;
      text-transform: uppercase
    }

    /* ── SEARCH & FILTER TOOLBAR ───────────────────────────────────────────── */
    .admin-filter-bar {
      display: flex;
      align-items: center;
      gap: .65rem;
      flex-wrap: wrap;
      margin-bottom: 1.25rem;
      padding: .75rem 1rem;
      background: color-mix(in oklab, var(--ks-ink) 3%, var(--ks-surface));
      border-radius: 10px;
      border: 1px solid var(--ks-line)
    }

    .admin-filter-bar input[type="text"] {
      flex: 1;
      min-width: 160px;
      max-width: 220px;
      padding: 7px 12px;
      border-radius: var(--ks-r-control-sm);
      background: var(--ks-surface);
      border: 1px solid var(--ks-line-strong);
      color: var(--ks-ink);
      font-size: .72rem;
      font-family: 'Raleway', sans-serif
    }

    .admin-filter-bar input[type="text"]:focus {
      outline: none;
      border-color: var(--ks-accent);
      box-shadow: 0 0 0 2px color-mix(in oklab, var(--accent) 15%, transparent)
    }

    .admin-filter-bar input[type="text"]::placeholder {
      color: var(--ks-ink-3)
    }

    .admin-filter-bar select {
      padding: 7px 12px;
      border-radius: var(--ks-r-control-sm);
      background: var(--ks-surface);
      border: 1px solid var(--ks-line-strong);
      color: var(--ks-ink-2);
      font-size: .68rem;
      font-family: 'Raleway', sans-serif;
      cursor: pointer
    }

    .admin-filter-bar select:focus {
      outline: none;
      border-color: var(--ks-accent);
      box-shadow: 0 0 0 2px color-mix(in oklab, var(--accent) 15%, transparent)
    }

    .admin-filter-clear {
      font-size: .62rem;
      color: var(--ks-ink-3);
      cursor: pointer;
      padding: 4px 10px;
      border-radius: 4px;
      transition: color .15s;
      letter-spacing: 1px;
      text-transform: uppercase;
      font-weight: 600
    }

    .admin-filter-clear:hover {
      color: var(--ks-accent-strong)
    }

    .admin-user-count {
      font-size: .68rem;
      color: var(--ks-ink-3);
      margin-left: auto;
      white-space: nowrap
    }

    /* ── IMPROVED TABLE (light theme) ──────────────────────────────────────── */
    /* THE ZEBRA IS MIXED FROM THE SURFACE, NOT NAMED, AND THE RENDER IS WHY.
       This started as #FAFBFC/#F0F1F3 -- a two-step interaction ladder (even
       row, then even-row-hover) with no equivalent in the theme layer, so the
       first pass kept both as literals rather than collapse the ladder into one
       token. The authenticated dark-mode capture showed that was wrong: once
       the surrounding card became --ks-surface, a hardcoded near-white stripe
       stopped being invisible and became a glaring white band across a dark
       card, with theme ink on it at roughly 2.2:1. Keeping the literal was only
       safe while everything around it was also light.

       color-mix against --ks-surface says what the ladder actually means -- a
       whisper off whatever this card is -- and it holds in both themes without
       inventing two more names for a step nothing else needs. The percentages
       reproduce the original spacing: 3% is the old #FAFBFC on white, 7% the
       old #F0F1F3, so light is unchanged and dark now has a ladder at all. */
    .admin-table {
      width: 100%;
      border-collapse: collapse
    }

    .admin-table th {
      font-size: .52rem;
      letter-spacing: 2.5px;
      text-transform: uppercase;
      color: var(--ks-ink-3);
      font-weight: 700;
      padding: .7rem .75rem;
      border-bottom: 2px solid var(--ks-line);
      text-align: left
    }

    .admin-table td {
      font-size: .78rem;
      color: var(--ks-ink-2);
      padding: .85rem .75rem;
      border-bottom: 1px solid var(--ks-line);
      vertical-align: middle
    }

    .admin-table tr {
      transition: background .15s ease
    }

    .admin-table tr:hover td {
      background: color-mix(in oklab, var(--ks-ink) 3%, var(--ks-surface))
    }

    .admin-table tbody tr:nth-child(even) td {
      background: color-mix(in oklab, var(--ks-ink) 3%, var(--ks-surface))
    }

    .admin-table tbody tr:nth-child(even):hover td {
      background: color-mix(in oklab, var(--ks-ink) 7%, var(--ks-surface))
    }

    /* ── AVATAR INITIALS ───────────────────────────────────────────────────── */
    .adm-avatar {
      width: 36px;
      height: 36px;
      border-radius: 50%;
      display: inline-flex;
      align-items: center;
      justify-content: center;
      font-size: .6rem;
      font-weight: 700;
      letter-spacing: 1px;
      /* A fixed ink on a tenant-controlled fill would only read for dojos that
         picked a light accent. The gradient is the accent to itself, so this
         is a flat accent circle and the initials must use the derived ink. */
      color: var(--ks-on-accent);
      flex-shrink: 0;
      background: linear-gradient(135deg, var(--ks-accent), var(--ks-accent));
      border: 2px solid color-mix(in oklab, var(--accent) 30%, transparent)
    }

    .adm-user-cell {
      display: flex;
      align-items: center;
      gap: 10px
    }

    .adm-user-name {
      font-weight: 600;
      font-size: .78rem;
      color: var(--ks-ink);
      line-height: 1.2
    }

    .adm-user-email {
      font-size: .6rem;
      color: var(--ks-ink-3);
      margin-top: 1px
    }

    /* ── BELT BADGES ───────────────────────────────────────────────────────── */
    /* LITERAL ON PURPOSE, and this is the clearest case in the file. A belt's
       colour is the data, not the styling: a red belt is red in every dojo, in
       every theme, whatever accent the tenant picked. These are the one group
       here that must NOT follow anything. Note .belt-red carries the same
       #FEE2E2/#991B1B/#FECACA triple the destructive controls used to -- which
       is exactly why those were converted one rule at a time rather than by
       replacing the value everywhere it appears. */
    .belt-badge {
      display: inline-block;
      padding: 4px 10px;
      border-radius: 6px;
      font-size: .52rem;
      font-weight: 800;
      letter-spacing: 1.5px;
      text-transform: uppercase;
      white-space: nowrap
    }

    .belt-white {
      background: var(--ks-canvas);
      color: var(--ks-ink-2);
      border: 1px solid var(--ks-line-strong)
    }

    .belt-yellow {
      background: #fef9c3;
      color: #92400e;
      border: 1px solid #fde68a
    }

    .belt-orange {
      background: #ffedd5;
      color: #9a3412;
      border: 1px solid #fed7aa
    }

    .belt-green {
      background: #dcfce7;
      color: #166534;
      border: 1px solid #bbf7d0
    }

    .belt-blue {
      background: #dbeafe;
      color: #1e40af;
      border: 1px solid #bfdbfe
    }

    .belt-purple {
      background: #f3e8ff;
      color: #6b21a8;
      border: 1px solid #e9d5ff
    }

    .belt-brown {
      background: #fef3c7;
      color: #78350f;
      border: 1px solid #fcd34d
    }

    .belt-red {
      background: #fee2e2;
      color: #991b1b;
      border: 1px solid #fecaca
    }

    .belt-black {
      background: #1f2937;
      color: #fff;
      border: 1px solid #374151
    }

    /* ── ROLE BADGES ───────────────────────────────────────────────────────── */
    /* LITERAL ON PURPOSE, and --ks-role-* is the wrong answer here even though
       the name matches. Those four are verified against the NAV BAND -- admin
       10.86:1, coach 7.23:1 -- which makes them light colours for a dark
       surface. These chips are light-on-light. Painting #5DADE2 as text on
       #DBEAFE would repeat exactly the theme-versus-surface mistake fixed in
       .dash-cal-weekdays below.

       Nor are they status. A competitor is not a "success" and a coach is not
       "info"; borrowing --ks-success-* here would make two unrelated meanings
       share a token and drift together forever after. Role colour on a light
       surface is a vocabulary the theme layer does not have, and inventing nine
       names for it is a design decision rather than a migration.

       .role-admin is the exception and was fixed -- see its own note. It is not
       a fixed categorical colour like these two; its background is the tenant's
       accent, so its ink has something to follow.

       STILL OPEN, recorded rather than touched: there is no .role-parent rule
       at all, though the role and its token both exist. */
    .role-badge {
      padding: 3px 10px;
      border-radius: 6px;
      font-size: .52rem;
      font-weight: 700;
      letter-spacing: 1.5px;
      text-transform: uppercase
    }

    /* DEFECT, measured at 2.26:1 in dark by the authenticated audit. Unlike its
       two siblings this chip is not a fixed categorical colour: its background
       is a wash of the TENANT's accent, and it was pairing that with a fixed
       gold-era amber. On a dark surface the amber stopped clearing anything,
       and for any dojo whose accent is not gold it was already the wrong
       family. --ks-accent-strong is the same colour as the wash, lightness
       adapted for text on whichever surface it lands on -- which is the only
       ink that can follow an accent-tinted chip. */
    .role-admin {
      background: color-mix(in oklab, var(--accent) 15%, transparent);
      color: var(--ks-accent-strong);
      border: 1px solid color-mix(in oklab, var(--accent) 30%, transparent)
    }

    .role-coach {
      background: #dbeafe;
      color: #1e40af;
      border: 1px solid #bfdbfe
    }

    .role-competitor {
      background: #dcfce7;
      color: #166534;
      border: 1px solid #bbf7d0
    }

    /* ── STATUS BADGES ─────────────────────────────────────────────────────── */
    .status-badge {
      padding: 3px 10px;
      border-radius: 6px;
      font-size: .52rem;
      font-weight: 700;
      letter-spacing: 1.5px;
      text-transform: uppercase
    }

    /* This one IS status, so it takes the status tokens -- the full tinted
       triple exists for exactly this shape of chip and is theme-aware, so the
       badge stops being unreadable the moment the page is dark.
       Note it now diverges slightly from .role-competitor's green, which stays
       literal above. That is correct rather than untidy: they looked identical
       by coincidence, and they do not mean the same thing. */
    .status-active {
      background: var(--ks-success-bg);
      color: var(--ks-success);
      border: 1px solid var(--ks-success-line)
    }

    .status-inactive {
      background: var(--ks-canvas);
      color: var(--ks-ink-3);
      border: 1px solid var(--ks-line)
    }

    /* ── FEED CARDS ────────────────────────────────────────────────────────── */
    .feed-card {
      min-width: 220px;
      max-width: 220px;
      background: var(--ks-surface);
      border: 1px solid var(--ks-line);
      border-radius: 12px;
      overflow: hidden;
      flex-shrink: 0;
      transition: transform .2s ease, box-shadow .2s ease;
      box-shadow: 0 1px 3px rgba(0, 0, 0, 0.04)
    }

    .feed-card:hover {
      transform: translateY(-3px);
      box-shadow: 0 8px 30px rgba(0, 0, 0, 0.1);
      border-color: color-mix(in oklab, var(--accent) 30%, transparent)
    }

    /* The quick-action button grid (.admin-quick-actions / .admin-qa-btn) was
       styled here for markup no page ever rendered. Deleted 2026-08-16. */

    /* ── ADMIN LIGHT-THEME TEXT OVERRIDES ──────────────────────────────────── */
    #view-admin .btn-outline,
    #view-admin .premium-btn-outline {
      color: var(--ks-ink-2);
      border-color: var(--ks-line-strong)
    }

    #view-admin .btn-outline:hover,
    #view-admin .premium-btn-outline:hover {
      color: var(--ks-accent-strong);
      border-color: var(--ks-accent)
    }

    /* Destructive, so it takes the danger triple. Note --ks-danger-line is
       #FECACA exactly, so the border does not move at all; the fill and ink
       shift by a step onto the system's values. The hover reuses -line as a
       fill because the family has a tint and a border but no hover step, and
       that reuse keeps the hover identical to what shipped. */
    #view-admin .btn-danger {
      background: var(--ks-danger-bg);
      color: var(--ks-danger);
      border: 1px solid var(--ks-danger-line)
    }

    #view-admin .btn-danger:hover {
      background: var(--ks-danger-line)
    }

    #view-admin .btn-ghost {
      color: var(--ks-ink-3);
      border-color: var(--ks-line)
    }

    #view-admin .btn-ghost:hover {
      color: var(--ks-ink);
      background: var(--ks-canvas)
    }

    #view-admin .fi-inp {
      background: var(--ks-surface);
      color: var(--ks-ink);
      border: 1px solid var(--ks-line-strong)
    }

    #view-admin .fi-inp:focus {
      border-color: var(--ks-accent);
      box-shadow: 0 0 0 2px color-mix(in oklab, var(--accent) 15%, transparent)
    }

    #view-admin .fl {
      color: var(--ks-ink-2)
    }

    #view-admin p {
      color: var(--ks-ink-3)
    }

    /* ── ADMIN CALENDAR LIGHT OVERRIDES ──────────────────────────────────── */
    #view-admin .admin-calendar-weekday {
      color: var(--ks-ink-3);
      border-bottom-color: var(--ks-line)
    }

    #view-admin .admin-calendar-day {
      background: var(--ks-surface);
      border-color: var(--ks-line);
      color: var(--ks-ink-2)
    }

    #view-admin .admin-calendar-day:hover {
      border-color: color-mix(in oklab, var(--accent) 40%, transparent)
    }

    #view-admin .admin-calendar-day.today {
      border-color: var(--ks-accent);
      background: #fffbeb
    }

    #view-admin .admin-calendar-selected {
      color: var(--ks-ink-3)
    }

    @media(max-width:900px) {
      .admin-stats {
        grid-template-columns: repeat(2, 1fr)
      }

      .admin-tabs {
        overflow-x: auto;
        flex-wrap: nowrap;
        padding: 0 1rem
      }

      .admin-tab {
        font-size: .58rem;
        padding: 10px 12px;
        white-space: nowrap
      }

      .admin-section {
        margin: .75rem .5rem;
        padding: 1rem .75rem;
        box-sizing: border-box;
        overflow: visible
      }

      .admin-welcome {
        padding: 1.25rem 1rem
      }

      .admin-welcome h2 {
        font-size: 1.1rem
      }

      .admin-topbar {
        padding: .75rem 1rem
      }

      .admin-topbar-search {
        margin: 0 .5rem;
        max-width: none;
        flex: 1
      }

      .admin-stats {
        padding: 1rem
      }

      .admin-tabs {
        padding: 0 1rem
      }

      .admin-filter-bar {
        padding: .5rem .75rem
      }

      /* Dashboard grid stack on mobile */
      /* minmax(0, 1fr), not 1fr. A 1fr track is minmax(auto, 1fr), and that auto
         floor will not shrink below the content's min-content width -- so on a
         412px phone this single column computed to 658px and every card in it
         overflowed by about 250px, with the document shell's overflow-x: hidden
         clipping the remainder out of reach rather than offering a scrollbar.
         The "View all" link sat at x=593, entirely off-screen. */
      .dash-two-col {
        grid-template-columns: minmax(0, 1fr) !important;
        padding: 0 .5rem !important;
        gap: .75rem
      }

      /* The grid's own padding is the gutter here. A card keeping its horizontal
         margin as well sat 22px in while still taking the full track width, so
         its right edge fell 6px outside the screen -- clipped, because the shell
         hides horizontal overflow rather than scrolling it. */
      .dash-two-col > .admin-section {
        margin-left: 0 !important;
        margin-right: 0 !important;
      }

      .dash-uploads-col,
      .dash-users-col {
        margin: 0;
        width: 100%;
        max-width: 100%;
        box-sizing: border-box
      }

      /* Every table wrapper scrolls horizontally */
      .upload-list-scroll,
      .dash-users-scroll,
      #admin-users-table,
      #admin-tournaments-table {
        overflow-x: auto;
        -webkit-overflow-scrolling: touch;
        width: 100%
      }

      /* Tables need enough width so columns aren't crushed, user can swipe to see all */
      .upload-list-table {
        min-width: 600px
      }

      .admin-table,
      #dash-users-table {
        min-width: 580px
      }

      /* Shrink table text on mobile */
      .upload-list-table th,
      .admin-table th {
        font-size: .5rem !important;
        padding: .5rem .4rem !important
      }

      .upload-list-table td,
      .admin-table td {
        font-size: .72rem !important;
        padding: .5rem .4rem !important
      }

      .adm-avatar {
        width: 28px;
        height: 28px;
        font-size: .5rem
      }

      .adm-user-name {
        font-size: .72rem !important
      }

      .adm-user-email {
        font-size: .55rem !important
      }

      .upload-thumb {
        width: 56px;
        height: 34px
      }

      /* Filter row compact */
      .dash-user-filter-row {
        flex-wrap: wrap;
        gap: .35rem
      }

      .dash-user-filter-row input[type="text"] {
        max-width: none;
        flex: 1 1 100%
      }

      /* Contain the whole admin view so page doesn't scroll horizontally */
      #view-admin {
        overflow-x: hidden
      }
    }

    /* ── UPLOAD SORT BAR ──────────────────────────────────────────────────────── */
    .upload-sort-bar {
      display: flex;
      align-items: center;
      gap: .65rem;
      margin-bottom: 1rem;
      flex-wrap: wrap
    }

    .upload-sort-bar label {
      font-size: .65rem;
      font-weight: 700;
      letter-spacing: 1px;
      text-transform: uppercase;
      color: var(--ks-ink-3)
    }

    .upload-sort-bar select {
      padding: 6px 10px;
      border-radius: var(--ks-r-control-sm);
      background: var(--ks-surface);
      border: 1px solid var(--ks-line-strong);
      color: var(--ks-ink-2);
      font-size: .7rem;
      font-family: 'Raleway', sans-serif;
      cursor: pointer
    }

    .upload-list-table {
      width: 100%;
      border-collapse: collapse
    }

    .upload-list-table th {
      font-size: .5rem;
      letter-spacing: 2px;
      text-transform: uppercase;
      color: var(--ks-ink-3);
      font-weight: 700;
      padding: .5rem .75rem;
      border-bottom: 2px solid var(--ks-line);
      text-align: left;
      cursor: pointer;
      user-select: none
    }

    .upload-list-table th:hover {
      color: var(--ks-ink)
    }

    .upload-list-table th .sort-arrow {
      margin-left: 4px;
      opacity: .4;
      font-size: .7rem
    }

    .upload-list-table th.sorted .sort-arrow {
      opacity: 1;
      color: var(--ks-accent-strong)
    }

    .upload-list-table td {
      font-size: .78rem;
      color: var(--ks-ink-2);
      padding: .75rem .75rem;
      border-bottom: 1px solid var(--ks-line);
      vertical-align: middle
    }

    .upload-list-table tr:hover td {
      background: color-mix(in oklab, var(--ks-ink) 3%, var(--ks-surface))
    }

    .upload-list-table tbody tr:nth-child(even) td {
      background: color-mix(in oklab, var(--ks-ink) 3%, var(--ks-surface))
    }

    .upload-list-table tbody tr:nth-child(even):hover td {
      background: color-mix(in oklab, var(--ks-ink) 7%, var(--ks-surface))
    }

    .upload-thumb {
      width: 72px;
      height: 44px;
      border-radius: 6px;
      overflow: hidden;
      background: #000;
      flex-shrink: 0;
      cursor: pointer;
      position: relative
    }

    .upload-thumb img {
      width: 100%;
      height: 100%;
      object-fit: cover
    }

    /* A match with no preview: the slot keeps its shape and says so with the
       video glyph on a quiet surface, instead of the black box reading
       "No Thumb" it used to show. */
    .upload-thumb-empty {
      width: 100%;
      height: 100%;
      display: flex;
      align-items: center;
      justify-content: center;
      background: var(--ks-surface-sunken, #EAECF0);
      color: var(--ks-ink-3, #667085);
    }

    .upload-thumb-empty .ks-icon {
      width: 18px;
      height: 18px;
    }

    .upload-thumb .play-ov {
      position: absolute;
      inset: 0;
      display: flex;
      align-items: center;
      justify-content: center;
      background: rgba(0, 0, 0, 0);
      transition: background .2s
    }

    .upload-thumb:hover .play-ov {
      background: rgba(0, 0, 0, 0.45)
    }

    .upload-thumb .play-ov::after {
      content: '▶';
      color: #fff;
      font-size: .7rem;
      opacity: 0;
      transition: opacity .2s
    }

    .upload-thumb:hover .play-ov::after {
      opacity: 1
    }

    /* ── DASHBOARD 2-COLUMN LAYOUT ───────────────────────────────────────────── */
    /* ── DASHBOARD GRID ROWS ─────────────────────────────────────────────────── */
    /* ROW 1: Uploads (38%) + Users (62%) */
    .dash-two-col {
      display: grid;
      grid-template-columns: 38% 1fr;
      gap: 1.25rem;
      align-items: stretch;
      padding: 0 1.75rem
    }

    /* ROW 2: Calendar (60%) + Right Panel (40%) — wider calendar */
    .dash-two-col.dash-cal-row {
      grid-template-columns: 68% 1fr;
      align-items: start
    }

    .dash-uploads-col {
      margin: 0;
      border-radius: 16px;
      display: flex;
      flex-direction: column
    }

    .dash-users-col {
      margin: 0;
      border-radius: 16px;
      overflow: hidden;
      display: flex;
      flex-direction: column
    }

    .upload-list-scroll {
      flex: 1;
      overflow-y: auto;
      overflow-x: auto;
      min-height: 200px;
      border-radius: 0 0 8px 8px
    }

    .dash-users-scroll {
      overflow-y: auto;
      max-height: 440px
    }

    .dash-user-filter-row {
      display: flex;
      align-items: center;
      gap: .4rem;
      flex-wrap: nowrap;
      margin-bottom: .65rem;
      background: color-mix(in oklab, var(--ks-ink) 3%, var(--ks-surface));
      border: 1px solid var(--ks-line);
      border-radius: 8px;
      padding: .45rem .65rem
    }

    .dash-user-filter-row input[type="text"] {
      flex: 1;
      min-width: 80px;
      max-width: 110px;
      padding: 5px 8px;
      border-radius: var(--ks-r-control-sm);
      background: var(--ks-surface);
      border: 1px solid var(--ks-line-strong);
      color: var(--ks-ink);
      font-size: .7rem;
      font-family: 'Raleway', sans-serif
    }

    .dash-user-filter-row input[type="text"]:focus {
      outline: none;
      border-color: var(--ks-accent)
    }

    .dash-user-filter-row input[type="text"]::placeholder {
      color: var(--ks-ink-3)
    }

    .dash-user-filter-row select {
      padding: 5px 7px;
      border-radius: var(--ks-r-control-sm);
      background: var(--ks-surface);
      border: 1px solid var(--ks-line-strong);
      color: var(--ks-ink-2);
      font-size: .65rem;
      font-family: 'Raleway', sans-serif;
      cursor: pointer
    }

    .dash-user-filter-row select:focus {
      outline: none;
      border-color: var(--ks-accent)
    }

    .dash-view-all-link {
      font-size: .62rem;
      font-weight: 700;
      letter-spacing: 1px;
      text-transform: uppercase;
      color: var(--ks-accent-strong);
      cursor: pointer;
      white-space: nowrap
    }

    .dash-view-all-link:hover {
      opacity: .8
    }

    .dash-user-count {
      font-size: .62rem;
      color: var(--ks-ink-3);
      margin-top: .5rem;
      text-align: right
    }

    /* Row gap between block rows */
    .dash-row-gap {
      height: 1.5rem
    }

    /* ── REFINED CARD ACCENTS (premium left-border) ───────────────────────────── */
    /* LITERAL ON PURPOSE — a categorical set, like the belts. Four dashboard
       cards are told apart by the hue of their left edge: uploads navy,
       calendar indigo, edit panel emerald, upcoming rose. Wayfinding, not
       status: the emerald does not mean success and the rose does not mean
       danger. Mapping any one of them to a semantic token would break the set
       into "three colours and one that follows the theme", which is worse than
       four values that are honestly just four values. */
    .admin-section {
      border-radius: 16px !important;
      box-shadow: 0 1px 4px rgba(0, 0, 0, 0.06), 0 1px 2px rgba(0, 0, 0, 0.03) !important;
      border: 1px solid var(--ks-line) !important
    }

    .dash-uploads-col.admin-section {
      border-left: 3px solid #0f1523 !important;
      background: var(--ks-surface) !important
    }

    .dash-users-col.admin-section {
      border-left: 3px solid var(--ks-accent) !important;
      background: var(--ks-surface) !important
    }

    .admin-section.dash-cal-section {
      border-left: 3px solid #6366f1 !important;
      background: var(--ks-surface) !important;
      box-shadow: 0 1px 4px rgba(0, 0, 0, 0.06), 0 1px 2px rgba(0, 0, 0, 0.03) !important
    }

    .dash-cal-edit-panel {
      border-left: 3px solid #10b981 !important;
      background: var(--ks-surface) !important;
      box-shadow: 0 1px 4px rgba(0, 0, 0, 0.06), 0 1px 2px rgba(0, 0, 0, 0.03) !important
    }

    #dash-upcoming-sidebar {
      background: var(--ks-surface);
      /* The first border-left that used to sit here was dead: the `border`
         shorthand two lines down resets all four edges, so only the second
         declaration ever painted. Removed as demonstrably obsolete rather than
         left as a decoy. The rose itself stays -- see the card-accent note. */
      border-radius: 16px;
      box-shadow: 0 1px 4px rgba(0, 0, 0, 0.06), 0 1px 2px rgba(0, 0, 0, 0.03);
      padding: 1.35rem;
      border: 1px solid var(--ks-line);
      border-left: 3px solid #f43f5e
    }

    @media(max-width:1100px) {
      .dash-two-col {
        grid-template-columns: minmax(0, 1fr);
        padding: 0 1rem;
        gap: .75rem
      }

      .dash-two-col.dash-cal-row {
        grid-template-columns: minmax(0, 1fr)
      }

      .dash-uploads-col,
      .dash-users-col {
        margin: 0
      }
    }

    /* ── BOLDER / BIGGER ADMIN TEXT ──────────────────────────────────────────── */
    .admin-section-title {
      font-size: .88rem !important;
      letter-spacing: 2px !important;
      font-weight: 800 !important
    }

    .admin-table th {
      font-size: .62rem !important;
      letter-spacing: 2px !important;
      font-weight: 800 !important
    }

    .admin-table td {
      font-size: .83rem !important;
      font-weight: 500 !important
    }

    .adm-user-name {
      font-size: .85rem !important;
      font-weight: 700 !important
    }

    .adm-user-email {
      font-size: .65rem !important;
      font-weight: 500 !important
    }

    .belt-badge {
      font-size: .58rem !important;
      font-weight: 900 !important
    }

    .role-badge {
      font-size: .58rem !important;
      font-weight: 800 !important
    }

    .status-badge {
      font-size: .58rem !important;
      font-weight: 800 !important
    }

    .upload-list-table th {
      font-size: .6rem !important;
      font-weight: 800 !important
    }

    .upload-list-table td {
      font-size: .8rem !important;
      font-weight: 500 !important
    }

    .admin-filter-bar select,
    .admin-filter-bar input[type="text"] {
      font-size: .76rem !important;
      font-weight: 600 !important
    }


    /* ── 3-DOT ACTION MENU ────────────────────────────────────────────────────── */
    .adm-actions-wrap {
      position: relative;
      display: inline-block
    }

    .adm-three-dot {
      width: 30px;
      height: 30px;
      border-radius: 6px;
      border: 1px solid var(--ks-line);
      background: var(--ks-surface);
      cursor: pointer;
      display: flex;
      align-items: center;
      justify-content: center;
      font-size: 1rem;
      color: var(--ks-ink-3);
      transition: all .15s;
      letter-spacing: .5px;
      user-select: none
    }

    .adm-three-dot:hover {
      background: var(--ks-canvas);
      border-color: var(--ks-line-strong);
      color: var(--ks-ink-2)
    }

    .adm-dropdown {
      position: absolute;
      right: 0;
      top: calc(100% + 4px);
      min-width: 160px;
      background: var(--ks-surface);
      border: 1px solid var(--ks-line);
      border-radius: 10px;
      box-shadow: 0 8px 24px rgba(0, 0, 0, 0.12);
      z-index: 200;
      overflow: hidden;
      display: none
    }

    .adm-dropdown.open {
      display: block
    }

    .adm-dd-item {
      display: flex;
      align-items: center;
      gap: 8px;
      padding: 9px 14px;
      font-size: .72rem;
      font-weight: 600;
      color: var(--ks-ink-2);
      cursor: pointer;
      transition: background .1s;
      white-space: nowrap
    }

    .adm-dd-item:hover {
      background: color-mix(in oklab, var(--ks-ink) 3%, var(--ks-surface))
    }

    .adm-dd-item .dd-icon {
      font-size: .85rem;
      width: 16px;
      text-align: center
    }

    .adm-dd-item.danger {
      color: var(--ks-danger)
    }

    .adm-dd-item.danger:hover {
      background: var(--ks-danger-bg)
    }

    .adm-dd-sep {
      border: none;
      border-top: 1px solid var(--ks-line);
      margin: 4px 0
    }

    /* ── BELT COLOR EDIT SWATCH ──────────────────────────────────────────────── */
    .belt-edit-cell {
      position: relative;
      display: inline-block
    }

    .belt-swatch-btn {
      display: inline-flex;
      align-items: center;
      gap: 5px;
      cursor: pointer
    }

    .belt-swatch-btn .edit-pencil {
      font-size: .65rem;
      color: var(--ks-ink-3);
      opacity: 0
    }

    .belt-swatch-btn:hover .edit-pencil {
      opacity: 1
    }

    /* ── CALENDAR 2-COL LAYOUT ───────────────────────────────────────────────── */
    .cal-layout {
      display: grid;
      grid-template-columns: 1fr 300px;
      gap: 1.5rem;
      align-items: start
    }

    .cal-edit-panel {
      background: var(--ks-surface);
      border: 1px solid var(--ks-line);
      border-radius: 14px;
      padding: 1.25rem;
      box-shadow: 0 1px 3px rgba(0, 0, 0, 0.04);
      position: sticky;
      top: 140px
    }

    .cal-edit-title {
      font-family: var(--ks-display);
      font-size: .75rem;
      letter-spacing: 2px;
      text-transform: uppercase;
      color: var(--ks-ink);
      font-weight: 700;
      margin-bottom: 1rem;
      padding-bottom: .5rem;
      border-bottom: 1px solid var(--ks-line);
      display: flex;
      justify-content: space-between;
      align-items: center
    }

    .cal-edit-title .close-x {
      cursor: pointer;
      font-size: .75rem;
      color: var(--ks-ink-3);
      padding: 2px 6px;
      border-radius: 4px;
      transition: all .15s
    }

    .cal-edit-title .close-x:hover {
      background: var(--ks-canvas);
      color: var(--ks-ink-2)
    }

    .cal-fg {
      margin-bottom: .75rem
    }

    .cal-fl {
      display: block;
      font-size: .62rem;
      font-weight: 700;
      letter-spacing: 1px;
      text-transform: uppercase;
      color: var(--ks-ink-3);
      margin-bottom: .3rem
    }

    .cal-inp {
      width: 100%;
      padding: 8px 10px;
      border-radius: 6px;
      border: 1px solid var(--ks-line-strong);
      background: var(--ks-surface);
      color: var(--ks-ink);
      font-size: .78rem;
      font-family: 'Raleway', sans-serif;
      box-sizing: border-box
    }

    .cal-inp:focus {
      outline: none;
      border-color: var(--ks-accent);
      box-shadow: 0 0 0 2px color-mix(in oklab, var(--accent) 15%, transparent)
    }

    .cal-inp-row {
      display: grid;
      grid-template-columns: 1fr 1fr;
      gap: .5rem
    }

    .cal-type-pills {
      display: flex;
      flex-wrap: wrap;
      gap: .4rem;
      margin-top: .25rem
    }

    .cal-type-pill {
      padding: 5px 10px;
      border-radius: 20px;
      font-size: .58rem;
      font-weight: 700;
      letter-spacing: 1px;
      text-transform: uppercase;
      border: 1px solid var(--ks-line);
      background: color-mix(in oklab, var(--ks-ink) 3%, var(--ks-surface));
      color: var(--ks-ink-3);
      cursor: pointer;
      transition: all .15s
    }

    .cal-type-pill.active {
      border-color: var(--ks-accent);
      background: color-mix(in oklab, var(--accent) 10%, transparent);
      color: #92400e
    }

    /* The .cal-banner-row / .cal-toggle fake switch (a div with no role, no
       tabindex and no keyboard path) is retired — every boolean row is the
       shared .ks-switch component now (ks-admin-surface-components.v1.css),
       which is a real checkbox. Its off-track literal moved there, with the
       same "literal on purpose" note. Deleted 2026-08-16. */

    .cal-save-btn {
      width: 100%;
      padding: 9px;
      border-radius: var(--ks-r-control);
      border: none;
      background: var(--ks-accent);
      /* Third instance of the same defect. */
      color: var(--ks-on-accent);
      font-size: .68rem;
      font-weight: 700;
      letter-spacing: 1.5px;
      text-transform: uppercase;
      cursor: pointer;
      font-family: 'Raleway', sans-serif;
      margin-top: .75rem;
      transition: all .2s
    }

    .cal-save-btn:hover {
      background: var(--ks-accent);
      box-shadow: 0 4px 12px color-mix(in oklab, var(--accent) 30%, transparent)
    }

    .cal-delete-btn {
      width: 100%;
      padding: 7px;
      border-radius: var(--ks-r-control);
      border: 1px solid var(--ks-danger-line);
      background: var(--ks-danger-bg);
      color: var(--ks-danger);
      font-size: .62rem;
      font-weight: 700;
      letter-spacing: 1.5px;
      text-transform: uppercase;
      cursor: pointer;
      font-family: 'Raleway', sans-serif;
      margin-top: .35rem;
      transition: all .2s
    }

    .cal-delete-btn:hover {
      background: var(--ks-danger-line)
    }

    .cal-color-swatch,
    .ann-color-swatch {
      display: inline-block;
      width: 24px;
      height: 24px;
      border-radius: 5px;
      cursor: pointer;
      border: 2px solid transparent;
      transition: all .15s;
      box-shadow: 0 1px 4px rgba(0, 0, 0, .2)
    }

    .cal-color-swatch:hover,
    .ann-color-swatch:hover {
      transform: scale(1.18);
      box-shadow: 0 3px 8px rgba(0, 0, 0, .25)
    }

    /* The selection ring sits on swatches of arbitrary user-chosen colour, so it
       has to be the strongest neutral rather than anything derived from what it
       is outlining. */
    .cal-color-swatch.selected,
    .ann-color-swatch.selected {
      border-color: var(--ks-ink);
      box-shadow: 0 0 0 3px rgba(26, 26, 46, .25)
    }

    /* ── Edit Panel Toggle Tabs ─────────────────────────────────────── */
    .cal-edit-tabs {
      display: flex;
      gap: 4px;
      padding: 4px;
      background: rgba(10, 19, 36, 0.06);
      border-radius: 9px;
      margin-bottom: 0.85rem;
    }

    .cal-edit-tab {
      flex: 1;
      padding: 0.5rem 0.6rem;
      text-align: center;
      cursor: pointer;
      font-size: 0.7rem;
      font-weight: 700;
      letter-spacing: 0.3px;
      border-radius: 6px;
      transition: background 0.18s ease, color 0.18s ease, box-shadow 0.18s ease;
      color: var(--ks-ink-3);
      user-select: none;
    }

    .cal-edit-tab:hover:not(.active) {
      color: var(--ks-ink);
    }

    .cal-edit-tab.active {
      background: var(--ks-surface);
      color: var(--ks-ink);
      box-shadow: 0 1px 3px rgba(0, 0, 0, 0.08);
    }


    /* ── UPCOMING EVENTS LIST ────────────────────────────────────────────────── */
    .upcoming-evt-row {
      display: flex;
      align-items: center;
      gap: .75rem;
      padding: .6rem 0;
      border-bottom: 1px solid var(--ks-line)
    }

    .upcoming-evt-row:last-child {
      border-bottom: none
    }

    .upcoming-date-badge {
      min-width: 46px;
      text-align: center;
      background: color-mix(in oklab, var(--ks-ink) 3%, var(--ks-surface));
      border: 1px solid var(--ks-line);
      border-radius: 8px;
      padding: .3rem .4rem;
      line-height: 1.2
    }

    .upcoming-date-badge .evt-month {
      font-size: .48rem;
      letter-spacing: 1.5px;
      text-transform: uppercase;
      color: var(--ks-ink-3);
      font-weight: 700
    }

    .upcoming-date-badge .evt-day {
      font-size: 1rem;
      font-weight: 700;
      color: var(--ks-ink);
      line-height: 1
    }

    .upcoming-evt-name {
      font-size: .78rem;
      font-weight: 600;
      color: var(--ks-ink);
      line-height: 1.2
    }

    .upcoming-evt-meta {
      font-size: .65rem;
      color: var(--ks-ink-3);
      margin-top: 2px
    }

    .evt-type-pill {
      display: inline-block;
      padding: 2px 7px;
      border-radius: 10px;
      font-size: .5rem;
      font-weight: 700;
      letter-spacing: 1px;
      text-transform: uppercase;
      margin-left: .4rem
    }

    /* LITERAL ON PURPOSE — event TYPE, another categorical set. Practice blue,
       tournament amber, team violet. They deliberately share the belt/role chip
       palette so every chip in the dashboard reads as one family. A tournament
       is not a warning and a practice is not info; the amber here means
       "tournament" and nothing else.
       Their solid counterparts (.admin-calendar-item.*, #ctp-*.active) keep a
       literal #fff ink for the same reason: the fill is fixed, so the ink has
       nothing to adapt to and a token would imply otherwise. The one exception
       worth recording is .other, which fills with the theme-aware --ks-ink-3
       and keeps white ink -- around 2.9:1 once the page is dark. Pre-existing,
       and left for the dark-mode pass rather than half-fixed here. */
    .evt-practice {
      background: #dbeafe;
      color: #1e40af
    }

    .evt-tournament {
      background: #fef3c7;
      color: #92400e
    }

    .evt-team {
      background: #f3e8ff;
      color: #6b21a8
    }

    .evt-other {
      background: var(--ks-canvas);
      color: var(--ks-ink-3)
    }

    .cal-no-evt {
      font-size: .78rem;
      color: var(--ks-ink-3);
      padding: .5rem 0
    }

    @media(max-width:1100px) {
      .cal-layout {
        grid-template-columns: 1fr
      }
    }

    @media(max-width:900px) {
      .cal-edit-panel {
        position: static
      }
    }

    /* ── DASHBOARD CALENDAR (embedded in dashboard tab) ─────────────────────── */
    /* Stretch both columns to same height; calendar fills full block width */
    .dash-two-col.dash-cal-row {
      align-items: stretch
    }

    .dash-cal-row {
      padding-top: 0
    }

    /* Remove side+bottom padding so calendar grid fills the full block edge-to-edge */
    .dash-cal-section {
      min-height: 0;
      overflow: visible;
      padding-left: 0 !important;
      padding-right: 0 !important;
      padding-bottom: 0 !important
    }

    /* Named helper classes keep horizontal padding for header / legend / selected bar */
    .dash-cal-hdr {
      padding: 1.25rem 1.25rem 0 1.25rem
    }

    .dash-cal-legend {
      padding: 0 1.25rem;
      margin-bottom: .9rem
    }

    .dash-cal-selected-bar {
      padding: 0 1.25rem
    }

    .dash-cal-grid-wrap {
      background: var(--ks-surface);
      border-radius: 0 0 16px 16px;
      overflow: hidden
    }

    /* DEFECT, found by the migration and fixed by it. This is a dark strip
       inside a light view, and --ks-accent-strong on the row below follows the
       THEME rather than the SURFACE: in light it resolves to
       --accent-on-surface, the lightness-CAPPED accent meant for text on white,
       and it was being painted on near-black. Riverside's #14418f came out
       around 1.4:1 -- weekday letters that are technically present.

       Pinning the variable on the dark container is the fix, not correcting the
       colour on each child. (This once cited dojo-how-it-works-section-header.v1.css
       as the idiom; that file was retired 2026-09-01 when its view stopped
       hand-painting surfaces and moved onto .ks-card--inverse, which re-points
       the type roles to the band inks and needs no pin at all — the better
       answer where a surface can use it.) --ks-band is the named dark surface,
       so the strip joins the band family instead of carrying its own
       near-black. */
    .dash-cal-weekdays {
      display: grid;
      grid-template-columns: repeat(7, 1fr);
      background: var(--ks-band);
      --ks-accent-strong: var(--accent-on-inverse);
      --ks-ink: var(--ks-band-ink);
      --ks-ink-2: var(--ks-band-ink-2);
      --ks-ink-3: var(--ks-band-ink-3)
    }

    .dash-cal-weekday {
      padding: 1rem .25rem;
      text-align: center;
      font-size: .9rem;
      font-weight: 900;
      letter-spacing: 2px;
      color: var(--ks-accent-strong);
      text-transform: uppercase
    }

    .dash-cal-grid {
      display: grid;
      grid-template-columns: repeat(7, 1fr)
    }

    /* Edit panel: static position so it doesn't overlap upcoming events */
    .dash-cal-edit-panel {
      border: 1px solid rgba(16, 185, 129, 0.2);
      border-radius: 16px;
      padding: 1.35rem;
      position: static;
      flex-shrink: 0
    }

    .dash-cal-selected {
      font-size: .72rem;
      color: var(--ks-ink-3);
      padding: .4rem .75rem;
      background: color-mix(in oklab, var(--ks-ink) 3%, var(--ks-surface));
      border: 1px solid var(--ks-line);
      border-radius: 8px;
      margin-bottom: .75rem
    }

    /* FULL-BLEED calendar day cells */
    #admin-tab-dashboard .admin-calendar-day {
      min-height: 100px;
      background: var(--ks-surface);
      border: 1px solid var(--ks-line);
      padding: .4rem .35rem;
      cursor: pointer;
      transition: all .15s;
      position: relative;
      vertical-align: top;
      box-sizing: border-box
    }

    #admin-tab-dashboard .admin-calendar-day:hover {
      border-color: color-mix(in oklab, var(--accent) 50%, transparent);
      background: #fffbf0
    }

    #admin-tab-dashboard .admin-calendar-day.today {
      border-color: var(--ks-accent);
      border-width: 2px;
      background: #fffbeb
    }

    #admin-tab-dashboard .admin-calendar-day.today .admin-calendar-day-num {
      color: var(--ks-accent-strong);
      font-weight: 900
    }

    #admin-tab-dashboard .admin-calendar-day.other-month {
      opacity: .22;
      background: color-mix(in oklab, var(--ks-ink) 3%, var(--ks-surface))
    }

    #admin-tab-dashboard .admin-calendar-day.selected {
      border-color: #6366f1;
      border-width: 3px;
      background: #eef2ff;
      box-shadow: inset 0 0 0 1px #6366f1
    }

    #admin-tab-dashboard .admin-calendar-day.selected .admin-calendar-day-num {
      color: #6366f1
    }

    /* DEFECT, found by the authenticated audit. The calendar TAB was missing
       from this selector, so its day numbers fell through to
       dojo-home-upcoming-widget.v1.css, which paints .admin-calendar-day-num
       with the legacy --white from an unscoped rule meant for a dark widget.
       White on the white calendar surface measured 1:1 -- the dates were not
       dim, they were invisible, and only a signed-in audit could see it.

       Fixed by naming the tab that was missing rather than by editing the
       widget: that rule is correct on its own dark surface, and narrowing it
       from here keeps the blast radius inside the file being migrated. */
    #admin-tab-dashboard .admin-calendar-day-num,
    #admin-tab-calendar .admin-calendar-day-num {
      font-size: 1.5rem;
      font-weight: 900;
      color: var(--ks-ink);
      line-height: 1;
      letter-spacing: -1px;
      display: block
    }

    /* LITERAL ON PURPOSE. A ghost affordance: near-invisible at rest, revealed
       by the hover rule below. The nearest token, --ks-ink-3, is a legible
       tertiary step and would make every empty day cell shout "+ ADD". That is
       a visual-design decision about how loud an empty day should be, not a
       token mapping, so the migration leaves the value and the question alone.
       Its resting contrast is ~1.5:1, which is recorded rather than fixed. */
    #admin-tab-dashboard .admin-calendar-day-add {
      font-size: .55rem;
      color: #d1d5db;
      font-weight: 700;
      letter-spacing: .5px
    }

    #admin-tab-dashboard .admin-calendar-day:hover .admin-calendar-day-add {
      color: var(--ks-accent-strong)
    }

    /* FULL-BLEED chips — fill entire width, max font, no gap, no radius */
    #admin-tab-dashboard .admin-calendar-items {
      padding: 0 0 2px 0
    }

    #admin-tab-dashboard .admin-calendar-item {
      display: block;
      width: 100%;
      text-align: left;
      border: none;
      border-radius: 0;
      padding: 5px 6px;
      margin-bottom: 2px;
      cursor: pointer;
      font-family: 'Raleway', sans-serif;
      transition: filter .12s;
      box-sizing: border-box;
      box-shadow: 0 1px 4px rgba(0, 0, 0, .18)
    }

    #admin-tab-dashboard .admin-calendar-item:hover {
      filter: brightness(.88)
    }

    #admin-tab-dashboard .admin-calendar-item-title {
      font-size: .78rem;
      font-weight: 900;
      line-height: 1.2;
      display: block;
      white-space: nowrap;
      overflow: hidden;
      text-overflow: ellipsis;
      text-shadow: 0 1px 3px rgba(0, 0, 0, .2)
    }

    #admin-tab-dashboard .admin-calendar-item-meta {
      font-size: .6rem;
      font-weight: 700;
      opacity: .88;
      white-space: nowrap;
      overflow: hidden;
      text-overflow: ellipsis;
      display: block
    }

    /* Vivid event type colors */
    #admin-tab-dashboard .admin-calendar-item.practice {
      background: #3b82f6;
      color: #fff
    }

    #admin-tab-dashboard .admin-calendar-item.tournament {
      background: #f59e0b;
      color: #fff
    }

    #admin-tab-dashboard .admin-calendar-item.team {
      background: #8b5cf6;
      color: #fff
    }

    #admin-tab-dashboard .admin-calendar-item.other {
      background: var(--ks-ink-3);
      color: #fff
    }

    /* Cal type pill colors matching event types */
    #ctp-practice.active {
      background: #3b82f6;
      border-color: #3b82f6;
      color: #fff
    }

    #ctp-tournament.active {
      background: #f59e0b;
      border-color: #f59e0b;
      color: #fff
    }

    #ctp-team.active {
      background: #8b5cf6;
      border-color: #8b5cf6;
      color: #fff
    }

    #ctp-other.active {
      background: var(--ks-ink-3);
      border-color: var(--ks-ink-3);
      color: #fff
    }

    /* Upcoming Events Sidebar — vertical bold list */
    #dash-upcoming-sidebar .upcoming-bold-card {
      border-radius: 10px;
      padding: .85rem 1rem;
      margin-bottom: .75rem;
      background: var(--ks-surface);
      border-left: 5px solid var(--ks-line);
      box-shadow: 0 2px 10px rgba(0, 0, 0, 0.07);
      cursor: pointer;
      transition: all .15s
    }

    #dash-upcoming-sidebar .upcoming-bold-card:hover {
      transform: translateX(3px);
      box-shadow: 0 4px 16px rgba(0, 0, 0, 0.13)
    }

    #dash-upcoming-sidebar .upcoming-bold-card.evt-practice-card {
      border-left-color: #3b82f6;
      background: var(--ks-surface)
    }

    #dash-upcoming-sidebar .upcoming-bold-card.evt-tournament-card {
      border-left-color: #f59e0b;
      background: var(--ks-surface)
    }

    #dash-upcoming-sidebar .upcoming-bold-card.evt-team-card {
      border-left-color: #8b5cf6;
      background: var(--ks-surface)
    }

    #dash-upcoming-sidebar .upcoming-bold-card.evt-other-card {
      border-left-color: var(--ks-ink-3);
      background: var(--ks-surface)
    }

    #dash-upcoming-sidebar .ubc-date {
      font-size: .58rem;
      font-weight: 800;
      letter-spacing: 2px;
      text-transform: uppercase;
      color: var(--ks-ink-3);
      margin-bottom: .2rem
    }

    #dash-upcoming-sidebar .ubc-title {
      font-size: 1rem;
      font-weight: 900;
      color: var(--ks-ink);
      line-height: 1.2;
      margin-bottom: .25rem
    }

    #dash-upcoming-sidebar .ubc-meta {
      font-size: .65rem;
      font-weight: 600;
      color: var(--ks-ink-3)
    }

    /* ── FOCUS-VISIBLE (keyboard accessibility) ──────────────────────────── */
    #view-admin button:focus-visible,
    #view-admin a:focus-visible,
    #view-admin input:focus-visible,
    #view-admin select:focus-visible,
    #view-admin textarea:focus-visible,
    #view-admin .admin-tab:focus-visible {
      outline: 2px solid var(--ks-accent);
      outline-offset: 2px
    }

    /* ── PREFERS-REDUCED-MOTION ─────────────────────────────────────────── */
    @media (prefers-reduced-motion: reduce) {

      #view-admin *,
      #view-admin *::before,
      #view-admin *::after {
        animation-duration: 0.01ms !important;
        animation-iteration-count: 1 !important;
        transition-duration: 0.01ms !important;
        scroll-behavior: auto !important
      }
    }


/* ══════════════════════════════════════════════════════════════════════
   dojo-rules-page.v1.css
   ══════════════════════════════════════════════════════════════════════ */
    /* ── RULES PAGE (legacy selectors kept for JS compat) ───────────────────── */
    .rules-cell-editable[contenteditable="true"] {
      outline: 1px dashed color-mix(in oklab, var(--accent) 50%, transparent);
      border-radius: 3px;
      padding: 2px 4px;
      background: color-mix(in oklab, var(--accent) 4%, transparent)
    }

    .rules-edit-note {
      display: none;
      text-align: center;
      font-size: .68rem;
      color: var(--muted);
      padding: .75rem 0 0;
      letter-spacing: .5px
    }

    .coach-edit .rules-edit-note {
      display: block
    }

    .rules-del-btn {
      display: none;
      background: none;
      border: none;
      cursor: pointer;
      color: var(--dim);
      font-size: .85rem;
      padding: 4px 6px;
      border-radius: var(--ks-r-control-sm);
      transition: all .2s;
      line-height: 1
    }

    .rules-del-btn:hover {
      color: var(--ks-danger);
      background: rgba(214, 69, 69, 0.12)
    }

    .coach-edit .rules-del-btn {
      display: inline-block
    }

    /* Add Rule Form */
    .rules-add-form {
      display: none;
      background: var(--white);
      border: 1px solid rgba(0, 0, 0, 0.1);
      border-radius: 6px;
      padding: 1.25rem;
      margin: 1.25rem auto;
      max-width: 1100px;
      box-shadow: 0 10px 30px rgba(0, 0, 0, 0.05)
    }

    .rules-add-form.open {
      display: block
    }

    .rules-add-form .form-row {
      display: flex;
      gap: .75rem;
      flex-wrap: wrap;
      margin-bottom: .75rem
    }

    .rules-add-form .fg {
      flex: 1;
      min-width: 160px;
      display: flex;
      flex-direction: column;
      gap: .3rem
    }

    .rules-add-form label {
      font-size: .6rem;
      letter-spacing: 2px;
      text-transform: uppercase;
      color: #444
    }

    .rules-add-form input,
    .rules-add-form select,
    .rules-add-form textarea {
      background: #f9f9f9;
      border: 1px solid #ddd;
      border-radius: var(--ks-r-control-sm);
      color: #111;
      padding: .5rem .75rem;
      font-family: 'Raleway', sans-serif;
      font-size: .78rem;
      outline: none;
      transition: border-color .2s
    }

    .rules-add-form input:focus,
    .rules-add-form select:focus,
    .rules-add-form textarea:focus {
      border-color: color-mix(in oklab, var(--accent) 50%, transparent)
    }

    .rules-add-form textarea {
      resize: vertical;
      min-height: 60px
    }

    .rules-add-form-btns {
      display: flex;
      gap: .5rem;
      margin-top: .25rem
    }

    .raf-status-toggle {
      display: flex;
      gap: .5rem
    }

    .raf-status-btn {
      flex: 1;
      padding: 7px;
      border-radius: var(--ks-r-control-sm);
      font-size: .62rem;
      font-weight: 700;
      letter-spacing: 1.5px;
      text-transform: uppercase;
      cursor: pointer;
      border: 1px solid #ddd;
      background: #eee;
      color: #666;
      transition: all .2s
    }

    .raf-status-btn.active-same {
      background: rgba(60, 179, 113, 0.12);
      border-color: rgba(60, 179, 113, 0.4);
      color: #3CB371
    }

    .raf-status-btn.active-differs {
      background: rgba(214, 69, 69, 0.12);
      border-color: rgba(214, 69, 69, 0.4);
      color: var(--ks-danger)
    }

    /* Restore Bar */
    .rules-restore-bar {
      display: none;
      margin-bottom: 1rem;
      padding: .6rem 1rem;
      background: color-mix(in oklab, var(--accent) 6%, transparent);
      border: 1px solid color-mix(in oklab, var(--accent) 20%, transparent);
      border-radius: 4px;
      font-size: .72rem;
      color: var(--muted);
      align-items: center;
      gap: .75rem;
      max-width: 1100px;
      margin-left: auto;
      margin-right: auto
    }

    .rules-restore-bar.visible {
      display: flex
    }

    .rules-restore-bar button {
      padding: 5px 14px;
      font-size: .62rem;
      font-weight: 700;
      letter-spacing: 1.5px;
      text-transform: uppercase;
      border-radius: var(--ks-r-control-sm);
      cursor: pointer;
      background: color-mix(in oklab, var(--accent) 10%, transparent);
      color: var(--ks-accent-strong);
      border: 1px solid color-mix(in oklab, var(--accent) 40%, transparent);
      transition: all .2s
    }

    /* ── LIGHT THEME SECTION OVERRIDE ─────────────────────────────────────── */


    #view-rules {
      /* min-height dropped: the body is a flex column and .view.active grows
         into the space instead, so the canvas still reaches the bottom of a
         short page without a viewport of it appearing above the footer. */
      background: var(--ks-canvas);
      padding: 0;
    }

    /* Rules Custom Header */
    .rules-local-header {
      display: flex;
      align-items: center;
      justify-content: space-between;
      padding: 1.5rem 0 3rem;
      border-bottom: 1px solid rgba(0, 0, 0, 0.05);
      margin-bottom: 3rem
    }

    .rl-lh-logo {
      display: flex;
      align-items: center;
      gap: 1.5rem
    }

    .rl-lh-logo img {
      width: 70px;
      height: 70px;
      border-radius: 50%;
      border: 3px solid #FFF;
      box-shadow: 0 10px 20px rgba(0, 0, 0, 0.1)
    }

    .rl-lh-text {
      font-size: 1.5rem;
      font-weight: 900;
      color: #0F172A;
      letter-spacing: -0.5px
    }

    .rl-lh-link {
      background: #FFF;
      color: #0F172A;
      text-decoration: none;
      font-size: .7rem;
      font-weight: 800;
      letter-spacing: 1px;
      text-transform: uppercase;
      padding: 12px 24px;
      border-radius: 30px;
      box-shadow: 0 4px 15px rgba(0, 0, 0, 0.05);
      transition: all .2s;
      border: 1px solid #E2E8F0
    }

    .rl-lh-link:hover {
      box-shadow: 0 8px 25px rgba(0, 0, 0, 0.1);
      transform: translateY(-2px)
    }

    @media(max-width:600px) {
      .rules-local-header {
        flex-direction: column;
        gap: 1.5rem;
        text-align: center
      }

      .rl-lh-logo {
        flex-direction: column;
        gap: 1rem
      }
    }

    .rl-hero-bg-container {
      width: 100%;
      background: var(--bg);
      background-image: radial-gradient(ellipse at 50% 0%, color-mix(in oklab, var(--accent) 6%, transparent) 0%, transparent 60%), url('https://www.transparenttextures.com/patterns/dark-matter.png');
      padding-top: 4rem;
      margin-bottom: 2rem;
      border-bottom: 1px solid rgba(255, 255, 255, 0.03)
    }

    .rl-hero-wrap {
      position: relative;
      max-width: 1150px;
      margin: 0 auto;
      padding: 0 1.5rem 4rem;
      display: flex;
      flex-direction: column
    }

    .rl-hero-bg-silhouette {
      position: absolute;
      top: 2rem;
      right: -2rem;
      width: 450px;
      height: 450px;
      object-fit: cover;
      border-radius: 50%;
      mix-blend-mode: screen;
      filter: grayscale(1) opacity(0.04);
      pointer-events: none;
      z-index: 0
    }

    @media(max-width:800px) {
      .rl-hero-bg-silhouette {
        display: none
      }
    }

    /* Text Area */
    .rl-hero-text {
      position: relative;
      z-index: 2;
      margin-bottom: 4rem
    }

    .rl-accent-kicker {
      display: block;
      font-family: var(--ks-display);
      font-weight: 700;
      font-style: italic;
      font-size: 1.6rem;
      color: #E67E22;
      margin-left: 2.4rem;
      margin-bottom: -0.6rem;
      position: relative;
      z-index: 3
    }

    .rl-hero-h1 {
      font-family: 'Inter', sans-serif;
      font-weight: 900;
      font-size: 3.5rem;
      color: var(--white);
      line-height: 1.1;
      margin: 0 0 1rem;
      letter-spacing: -1.5px
    }

    @media(max-width:600px) {
      .rl-hero-h1 {
        font-size: 2.8rem
      }
    }

    .rl-hero-desc {
      font-size: 1.1rem;
      color: var(--muted);
      line-height: 1.6;
      font-weight: 600
    }

    /* Cards Row */
    .rl-org-cards {
      display: grid;
      grid-template-columns: 1fr 1fr;
      gap: 2rem;
      position: relative;
      z-index: 2
    }

    @media(max-width:800px) {
      .rl-org-cards {
        grid-template-columns: 1fr;
        gap: 2rem
      }
    }

    .rl-org-card {
      background: #FFF;
      border-radius: 16px;
      padding: 3rem 2.5rem;
      box-shadow: 0 15px 40px rgba(0, 0, 0, 0.06);
      position: relative;
      display: flex;
      flex-direction: column;
      gap: 1.25rem
    }

    .rl-org-card.aau {
      padding: 0;
      border: none;
      overflow: hidden;
      background: #FFFFFF;
      box-shadow: 0 24px 64px rgba(0, 28, 100, 0.13), 0 4px 16px rgba(0, 28, 100, 0.07)
    }

    /* AAU Premium Card */
    .aau-card-hdr {
      background: linear-gradient(155deg, #001A5E 0%, #002F96 55%, #001D6E 100%);
      padding: 1.9rem 2rem 1.55rem;
      position: relative;
      overflow: hidden;
      display: flex;
      flex-direction: column;
      align-items: center;
      text-align: center
    }

    .aau-card-hdr::before {
      content: '';
      position: absolute;
      top: 0;
      left: 0;
      right: 0;
      height: 5px;
      background: linear-gradient(90deg, #8B0000 0%, #CC0020 50%, #8B0000 100%)
    }

    .aau-card-hdr::after {
      content: '';
      position: absolute;
      inset: 0;
      background: radial-gradient(ellipse at 80% 20%, rgba(191, 10, 48, 0.13) 0%, transparent 60%);
      pointer-events: none
    }

    .aau-ruleset-tag {
      position: absolute;
      top: 1rem;
      right: 1rem;
      font-size: .5rem;
      font-weight: 800;
      letter-spacing: 2.5px;
      text-transform: uppercase;
      color: rgba(255, 255, 255, 0.42);
      border: 1px solid rgba(255, 255, 255, 0.14);
      padding: 3px 9px;
      border-radius: 20px
    }

    .aau-shield-img {
      width: 74px;
      height: auto;
      margin: .4rem 0 .9rem;
      filter: drop-shadow(0 6px 20px rgba(0, 0, 0, 0.45));
      position: relative;
      z-index: 1;
      object-fit: contain
    }

    .aau-hdr-name {
      font-family: var(--ks-display);
      font-size: 1.12rem;
      font-weight: 700;
      color: #FFFFFF;
      letter-spacing: 4px;
      line-height: 1.1;
      position: relative;
      z-index: 1;
      margin-bottom: .3rem
    }

    .aau-hdr-sub {
      font-size: .57rem;
      font-weight: 700;
      letter-spacing: 2.5px;
      text-transform: uppercase;
      color: #C9A84C;
      position: relative;
      z-index: 1
    }

    .aau-card-body {
      padding: 1.55rem 2rem 1.9rem;
      display: flex;
      flex-direction: column;
      gap: 1.05rem;
      flex: 1
    }

    .aau-stat-wrap {
      display: flex;
      align-items: baseline;
      gap: .45rem;
      padding-bottom: 1.1rem;
      border-bottom: 2px solid #F1F5F9
    }

    .aau-big-num {
      font-size: 3.2rem;
      font-weight: 900;
      color: #001A5E;
      line-height: 1;
      letter-spacing: -2px
    }

    .aau-big-lbl {
      font-size: .9rem;
      font-weight: 700;
      color: #475569
    }

    .aau-feats {
      list-style: none;
      padding: 0;
      margin: 0;
      display: flex;
      flex-direction: column;
      gap: .48rem;
      flex: 1
    }

    .aau-feats li {
      display: flex;
      align-items: center;
      gap: .6rem;
      font-size: .79rem;
      font-weight: 600;
      color: #334155;
      line-height: 1.4
    }

    .aau-feats li::before {
      content: '';
      width: 5px;
      height: 5px;
      border-radius: 50%;
      background: #BF0A30;
      flex-shrink: 0
    }

    .rl-org-card.aau .rl-card-btn {
      background: #F4D03F;
      color: #050505;
      border: 1px solid #D4B82C;
      box-shadow: 0 4px 14px rgba(244, 208, 63, 0.3);
      margin-top: .4rem
    }

    .rl-org-card.aau .rl-card-btn:hover {
      background: #D4B82C;
      color: #050505;
      border-color: #C4A81C;
      transform: translateY(-2px);
      box-shadow: 0 8px 24px rgba(212, 184, 44, 0.4)
    }

    .rl-org-card.nkf {
      padding: 0;
      border: none;
      overflow: hidden;
      background: #FFFFFF;
      box-shadow: 0 24px 64px rgba(0, 30, 80, 0.11), 0 4px 16px rgba(0, 30, 80, 0.06)
    }

    /* NKF Premium Card */
    .nkf-card-hdr {
      background: linear-gradient(155deg, #1A1A2E 0%, #16213E 55%, #0F3460 100%);
      padding: 1.9rem 2rem 1.55rem;
      position: relative;
      overflow: hidden;
      display: flex;
      flex-direction: column;
      align-items: center;
      text-align: center
    }

    .nkf-card-hdr::before {
      content: '';
      position: absolute;
      top: 0;
      left: 0;
      right: 0;
      height: 5px;
      background: linear-gradient(90deg, #1565A0 0%, #2980B9 50%, #1565A0 100%)
    }

    .nkf-card-hdr::after {
      content: '';
      position: absolute;
      inset: 0;
      background: radial-gradient(ellipse at 80% 20%, rgba(41, 128, 185, 0.15) 0%, transparent 60%);
      pointer-events: none
    }

    .nkf-ruleset-tag {
      position: absolute;
      top: 1rem;
      right: 1rem;
      font-size: .5rem;
      font-weight: 800;
      letter-spacing: 2.5px;
      text-transform: uppercase;
      color: rgba(255, 255, 255, 0.42);
      border: 1px solid rgba(255, 255, 255, 0.14);
      padding: 3px 9px;
      border-radius: 20px
    }

    .nkf-shield-img {
      width: 74px;
      height: auto;
      margin: .4rem 0 .9rem;
      filter: drop-shadow(0 6px 20px rgba(0, 0, 0, 0.45));
      position: relative;
      z-index: 1;
      object-fit: contain
    }

    .nkf-hdr-name {
      font-family: var(--ks-display);
      font-size: 1.12rem;
      font-weight: 700;
      color: #FFFFFF;
      letter-spacing: 4px;
      line-height: 1.1;
      position: relative;
      z-index: 1;
      margin-bottom: .3rem
    }

    .nkf-hdr-sub {
      font-size: .57rem;
      font-weight: 700;
      letter-spacing: 2.5px;
      text-transform: uppercase;
      color: #64B5F6;
      position: relative;
      z-index: 1
    }

    .nkf-card-body {
      padding: 1.55rem 2rem 1.9rem;
      display: flex;
      flex-direction: column;
      gap: 1.05rem;
      flex: 1
    }

    .nkf-stat-wrap {
      display: flex;
      align-items: baseline;
      gap: .45rem;
      padding-bottom: 1.1rem;
      border-bottom: 2px solid #F1F5F9
    }

    .nkf-big-num {
      font-size: 3.2rem;
      font-weight: 900;
      color: #0F3460;
      line-height: 1;
      letter-spacing: -2px
    }

    .nkf-big-lbl {
      font-size: .9rem;
      font-weight: 700;
      color: #475569
    }

    .nkf-feats {
      list-style: none;
      padding: 0;
      margin: 0;
      display: flex;
      flex-direction: column;
      gap: .48rem;
      flex: 1
    }

    .nkf-feats li {
      display: flex;
      align-items: center;
      gap: .6rem;
      font-size: .79rem;
      font-weight: 600;
      color: #334155;
      line-height: 1.4
    }

    .nkf-feats li::before {
      content: '';
      width: 5px;
      height: 5px;
      border-radius: 50%;
      background: #2980B9;
      flex-shrink: 0
    }

    .rl-org-card.nkf .rl-card-btn {
      background: #0033A0;
      color: #FFF;
      border: 1px solid #002880;
      box-shadow: 0 4px 14px rgba(0, 51, 160, 0.3);
      margin-top: .4rem
    }

    .rl-org-card.nkf .rl-card-btn:hover {
      background: #002880;
      border-color: #001E60;
      transform: translateY(-2px);
      box-shadow: 0 8px 24px rgba(0, 40, 128, 0.4)
    }

    .card-pill.aau-pill {
      color: #E67E22;
      background: rgba(245, 176, 65, 0.12);
      align-self: flex-start
    }

    .card-pill.nkf-pill {
      color: #2980B9;
      background: rgba(52, 152, 219, 0.12);
      align-self: flex-start
    }

    .card-pill {
      display: inline-flex;
      padding: 6px 16px;
      border-radius: 30px;
      font-size: .65rem;
      font-weight: 800;
      letter-spacing: 2px;
      text-transform: uppercase;
      margin-bottom: .5rem
    }

    .rl-card-top {
      display: flex;
      gap: 1.5rem;
      align-items: center;
      margin-bottom: 1rem
    }

    .rl-card-icon {
      width: 64px;
      height: 64px;
      border-radius: 12px;
      display: flex;
      align-items: center;
      justify-content: center;
      flex-shrink: 0;
      font-size: 1.8rem
    }

    .rl-org-card.aau .rl-card-icon {
      background: rgba(245, 176, 65, 0.1);
      border: 1px solid rgba(245, 176, 65, 0.3);
      color: #E67E22
    }

    .rl-org-card.aau .rl-card-icon svg {
      width: 36px;
      height: 36px;
      stroke: #E67E22
    }

    .rl-org-card.nkf .rl-card-icon {
      background: rgba(52, 152, 219, 0.1);
      border: 1px solid rgba(52, 152, 219, 0.3);
      color: #2980B9
    }

    .rl-org-card.nkf .rl-card-icon svg {
      width: 36px;
      height: 36px;
      stroke: #2980B9
    }

    .rl-card-title {
      font-size: 1.6rem;
      font-weight: 900;
      color: #0F172A;
      margin-bottom: .25rem;
      letter-spacing: -0.5px
    }

    .rl-card-sub {
      font-size: .9rem;
      color: #475569;
      font-weight: 600
    }

    .rl-card-stat {
      display: flex;
      align-items: baseline;
      gap: .5rem;
      margin-bottom: 1.5rem
    }

    .rl-stat-num {
      font-size: 4rem;
      font-weight: 900;
      color: #0F172A;
      line-height: 1
    }

    .rl-stat-text {
      font-size: 1.05rem;
      color: #475569;
      font-weight: 700
    }

    .rl-card-btn {
      display: inline-flex;
      align-items: center;
      justify-content: center;
      gap: .75rem;
      padding: 16px;
      border-radius: var(--ks-r-control);
      font-size: .7rem;
      font-weight: 800;
      letter-spacing: 1px;
      text-transform: uppercase;
      text-decoration: none;
      transition: all .2s;
      text-align: center;
      width: 100%;
      box-sizing: border-box
    }

    .rl-card-btn path {
      stroke-width: 2.5
    }

    .rl-org-card.aau .rl-card-btn {
      background: #F4D03F;
      color: #050505;
      border: 1px solid #D4B82C;
      box-shadow: 0 4px 14px rgba(244, 208, 63, 0.3)
    }

    .rl-org-card.aau .rl-card-btn:hover {
      background: #D4B82C;
      color: #050505;
      border-color: #C4A81C;
      transform: translateY(-2px);
      box-shadow: 0 8px 24px rgba(212, 184, 44, 0.4)
    }

    .rl-org-card.nkf .rl-card-btn {
      background: #0033A0;
      color: #FFF;
      border: 1px solid #002880;
      box-shadow: 0 4px 14px rgba(0, 51, 160, 0.3)
    }

    .rl-org-card.nkf .rl-card-btn:hover {
      background: #002880;
      border-color: #001E60;
      transform: translateY(-2px);
      box-shadow: 0 8px 24px rgba(0, 40, 128, 0.4)
    }

    /* Filter Bar — on the shared measure and gutter, like every other page's
       content. The page ran its own 1150px column for months, 50px narrower
       than everything around it, with a gutter that never breathed. */
    .rl-filter-bar {
      display: flex;
      gap: .75rem;
      flex-wrap: wrap;
      max-width: var(--ks-measure);
      margin: 0 auto 2rem;
      padding: 0 var(--ks-gutter)
    }

    .rl-filter-btn {
      padding: 12px 28px;
      border-radius: 30px;
      font-size: .7rem;
      font-weight: 800;
      letter-spacing: 1px;
      text-transform: uppercase;
      cursor: pointer;
      background: var(--ks-surface);
      border: 1px solid var(--ks-line);
      color: var(--ks-ink-3);
      transition: all .2s;
      box-shadow: 0 4px 10px rgba(0, 0, 0, 0.03)
    }

    .rl-filter-btn.active,
    .rl-filter-btn:hover {
      background: var(--ks-ink);
      color: var(--ks-surface);
      border-color: var(--ks-ink);
      box-shadow: 0 8px 20px rgba(15, 23, 42, 0.2)
    }

    .rl-filter-btn:focus-visible {
      outline: 2px solid var(--ks-focus-ring);
      outline-offset: 2px;
    }

    /* Table Section. The section-gap below is the page's own foot room —
       the platform banner that used to sit here carried it before. */
    .rl-table-section {
      width: 100%;
      max-width: var(--ks-measure);
      margin: 0 auto 0;
      padding: 0 var(--ks-gutter) var(--ks-section-gap);
      box-sizing: border-box
    }

    .rl-table-wrap {
      width: 100%;
      max-width: 100%;
      background: #FFF;
      border-radius: 16px;
      overflow-x: auto;
      -webkit-overflow-scrolling: touch;
      box-shadow: 0 20px 50px rgba(15, 23, 42, 0.08);
      border: 1px solid #E2E8F0;
      margin-bottom: 4rem;
      box-sizing: border-box
    }

    .rl-table {
      width: 100%;
      min-width: 600px;
      border-collapse: collapse
    }

    .rl-table thead th {
      padding: 1.5rem 2rem;
      font-size: .75rem;
      font-weight: 900;
      letter-spacing: 1px;
      text-transform: uppercase;
      color: #FFF;
      text-align: left
    }

    /* Specific Header Colors */
    .rl-table thead th:nth-child(1) {
      background: #0F172A;
      width: 30%
    }

    .rl-table thead th:nth-child(2) {
      background: #F4D03F;
      color: #050505;
      width: 35%
    }

    .rl-table thead th:nth-child(3) {
      background: #0033A0;
      width: 35%
    }

    .rl-tr {
      cursor: pointer;
      border-bottom: 1px solid #E2E8F0;
      transition: background .15s
    }

    .rl-tr:hover {
      background: #F8FAFC
    }

    .rl-tr:last-child {
      border-bottom: none
    }

    .rl-td {
      padding: 1.5rem 2rem;
      vertical-align: middle;
      font-size: .95rem;
      color: #1E293B;
      font-weight: 700
    }

    .rl-td:nth-child(1) {
      border-right: 1px solid #F1F5F9
    }

    .rl-td:nth-child(2) {
      border-right: 1px solid #F1F5F9;
      position: relative
    }

    .rl-cat-cell {
      display: flex;
      align-items: center;
      gap: 1.5rem
    }

    .rl-cat-icon {
      width: 50px;
      height: 50px;
      border-radius: 12px;
      background: #F1F5F9;
      border: 1px solid #E2E8F0;
      display: flex;
      align-items: center;
      justify-content: center;
      flex-shrink: 0;
      font-size: 1.6rem
    }

    .rl-cat-text-wrap strong {
      display: block;
      font-size: 1.05rem;
      color: #0F172A;
      margin-bottom: .3rem;
      font-weight: 800
    }

    .rl-cat-text-wrap span {
      font-size: .8rem;
      color: #64748B;
      font-weight: 600
    }

    .rl-val-wrap {
      display: flex;
      align-items: center;
      justify-content: space-between;
      gap: 1rem
    }

    /* Inline Badges inside AAU Column */
    .rl-badge {
      display: inline-flex;
      align-items: center;
      padding: 6px 10px;
      border-radius: 6px;
      font-size: .65rem;
      font-weight: 800;
      letter-spacing: 1px;
      text-transform: uppercase;
      flex-shrink: 0
    }

    .rl-badge.same {
      background: #D1FAE5;
      color: #059669
    }

    .rl-badge.differs {
      background: #E0E7FF;
      color: #4F46E5
    }

    /* Expand Row — animated via grid-template-rows */
    .rl-expand-row {
      background: #F8FAFC;
      border-bottom: 1px solid #E2E8F0
    }

    .rl-expand-cell {
      padding: 0 !important
    }

    .rl-expand-inner {
      display: grid;
      grid-template-rows: 0fr;
      transition: grid-template-rows .4s cubic-bezier(.4, 0, .2, 1)
    }

    .rl-expand-row.open .rl-expand-inner {
      grid-template-rows: 1fr
    }

    .rl-expand-content {
      overflow: hidden
    }

    .rl-expand-grid {
      display: grid;
      grid-template-columns: 1fr 1fr;
      gap: 3rem;
      padding: 2rem
    }

    @media(max-width:700px) {
      .rl-expand-grid {
        grid-template-columns: 1fr;
        gap: 2rem
      }
    }

    .rl-expand-col strong {
      font-size: .7rem;
      font-weight: 900;
      letter-spacing: 1.5px;
      text-transform: uppercase;
      color: #0F172A;
      display: block;
      margin-bottom: .75rem
    }

    .rl-expand-col p {
      font-size: .95rem;
      color: #475569;
      line-height: 1.7;
      margin: 0;
      font-weight: 500
    }

    /* Chevron indicator on table rows */
    .rl-row-chevron {
      display: inline-block;
      width: 16px;
      height: 16px;
      margin-left: auto;
      flex-shrink: 0;
      color: #94A3B8;
      transition: transform .35s cubic-bezier(.4, 0, .2, 1)
    }

    .rl-tr.expanded .rl-row-chevron {
      transform: rotate(180deg);
      color: #0F172A
    }

    /* ── RULES: PREMIUM MOBILE CARDS ─────────────────────────────────────── */
    .rl-cards-mobile {
      display: none
    }

    @media(max-width:768px) {
      .rl-table-wrap {
        display: none
      }

      .rules-edit-note {
        display: none !important
      }

      .rl-cards-mobile {
        display: flex;
        flex-direction: column;
        gap: .875rem;
        max-width: var(--ks-measure);
        margin: 0 auto 3rem;
        padding: 0 var(--ks-gutter);
        box-sizing: border-box
      }
    }

    .rl-rule-card {
      background: #FFF;
      border-radius: 16px;
      border: 1px solid rgba(226, 232, 240, .8);
      box-shadow: 0 4px 20px rgba(15, 23, 42, .06), 0 1px 3px rgba(15, 23, 42, .04);
      overflow: hidden;
      transition: box-shadow .25s ease, border-color .25s ease;
      position: relative
    }

    .rl-rule-card:active {
      box-shadow: 0 2px 8px rgba(15, 23, 42, .08)
    }

    .rl-rule-card.expanded {
      border-color: rgba(15, 23, 42, .12);
      box-shadow: 0 8px 32px rgba(15, 23, 42, .1), 0 2px 6px rgba(15, 23, 42, .05)
    }

    /* Card Header */
    .rl-rc-header {
      display: flex;
      align-items: center;
      gap: .875rem;
      padding: 1.125rem 1.25rem;
      cursor: pointer;
      -webkit-tap-highlight-color: transparent;
      user-select: none
    }

    .rl-rc-icon {
      width: 44px;
      height: 44px;
      border-radius: 12px;
      display: flex;
      align-items: center;
      justify-content: center;
      flex-shrink: 0;
      font-size: 1.3rem
    }

    .rl-rc-icon>div {
      width: 100% !important;
      height: 100% !important;
      border-radius: 12px !important;
      font-size: 1.3rem
    }

    .rl-rc-title-area {
      flex: 1;
      min-width: 0
    }

    .rl-rc-category {
      font-size: .92rem;
      font-weight: 800;
      color: #0F172A;
      line-height: 1.3;
      margin-bottom: .15rem
    }

    .rl-rc-sub {
      font-size: .72rem;
      color: #64748B;
      font-weight: 600;
      line-height: 1.3
    }

    .rl-rc-badge-area {
      display: flex;
      align-items: center;
      gap: .625rem;
      flex-shrink: 0
    }

    .rl-rc-chevron {
      width: 18px;
      height: 18px;
      color: #94A3B8;
      transition: transform .35s cubic-bezier(.4, 0, .2, 1);
      flex-shrink: 0
    }

    .rl-rule-card.expanded .rl-rc-chevron {
      transform: rotate(180deg);
      color: #0F172A
    }

    /* Summary Values — always visible */
    .rl-rc-summary {
      padding: 0 1.25rem .875rem
    }

    .rl-rc-val-row {
      display: flex;
      align-items: baseline;
      gap: .75rem;
      padding: .5rem 0;
      border-top: 1px solid #F1F5F9
    }

    .rl-rc-val-label {
      font-size: .58rem;
      font-weight: 800;
      letter-spacing: 2px;
      text-transform: uppercase;
      flex-shrink: 0;
      width: 34px;
      line-height: 1
    }

    .rl-rc-val-label.aau-label {
      color: #B8860B
    }

    .rl-rc-val-label.nkf-label {
      color: #0033A0
    }

    .rl-rc-val-text {
      font-size: .82rem;
      font-weight: 700;
      color: #1E293B;
      line-height: 1.45
    }

    /* Expandable Details — smooth accordion */
    .rl-rc-details {
      display: grid;
      grid-template-rows: 0fr;
      transition: grid-template-rows .4s cubic-bezier(.4, 0, .2, 1)
    }

    .rl-rule-card.expanded .rl-rc-details {
      grid-template-rows: 1fr
    }

    .rl-rc-details-inner {
      overflow: hidden
    }

    .rl-rc-details-pad {
      padding: 0 1.25rem 1.25rem
    }

    .rl-rc-detail-block {
      background: #F8FAFC;
      border: 1px solid #E2E8F0;
      border-radius: 12px;
      padding: 1rem 1.125rem;
      margin-bottom: .75rem
    }

    .rl-rc-detail-block:last-child {
      margin-bottom: 0
    }

    .rl-rc-detail-block strong {
      display: flex;
      align-items: center;
      gap: .5rem;
      font-size: .6rem;
      font-weight: 900;
      letter-spacing: 2px;
      text-transform: uppercase;
      color: #0F172A;
      margin-bottom: .625rem;
      padding-bottom: .5rem;
      border-bottom: 1px solid #E2E8F0
    }

    .rl-rc-detail-block strong .rl-rc-dot {
      width: 6px;
      height: 6px;
      border-radius: 50%;
      flex-shrink: 0
    }

    .rl-rc-detail-block strong .rl-rc-dot.aau-dot {
      background: #D4A017
    }

    .rl-rc-detail-block strong .rl-rc-dot.nkf-dot {
      background: #0033A0
    }

    .rl-rc-detail-block p {
      font-size: .85rem;
      color: #475569;
      line-height: 1.7;
      margin: 0;
      font-weight: 500
    }

    /* Card delete button */
    .rl-rule-card .rules-del-btn {
      position: absolute;
      top: .75rem;
      right: .75rem;
      z-index: 2
    }

    /* Mobile filter bar tweaks */
    @media(max-width:768px) {
      .rl-filter-bar {
        gap: .5rem;
        margin-bottom: 1.25rem;
        padding: 0 1rem
      }

      .rl-filter-btn {
        padding: 10px 20px;
        font-size: .65rem;
        flex: 1;
        text-align: center;
        min-width: 0
      }
    }

    /* Coach add rule button in rules edit wrap. Styled here rather than by
       the inline background it used to carry; font-size stays with the
       typography sheet. */
    .rules-add-btn {
      padding: 10px 24px;
      border-radius: var(--ks-r-pill);
      font-weight: 800;
      letter-spacing: 1px;
      text-transform: uppercase;
      cursor: pointer;
      background: var(--ks-surface);
      border: 1px solid var(--ks-line);
      color: var(--ks-ink-2);
      transition: border-color .2s, color .2s
    }

    .rules-add-btn:hover {
      border-color: var(--ks-accent);
      color: var(--ks-ink)
    }

    .rules-add-btn:focus-visible {
      outline: 2px solid var(--ks-focus-ring);
      outline-offset: 2px
    }

    .rl-add-btn-wrap {
      display: flex;
      justify-content: center;
      margin-bottom: 2rem
    }

    .coach-edit .rl-add-btn-wrap {
      display: flex
    }

    .rl-add-btn-wrap {
      display: none
    }

    /* hidden unless coach */


/* ══════════════════════════════════════════════════════════════════════
   dojo-find-tournaments.v1.css
   ══════════════════════════════════════════════════════════════════════ */
    /* ── FIND TOURNAMENTS ────────────────────────────────────────────────────── */
    .ft-search-panel {
      max-width: 860px;
      margin: 0 auto;
      padding: 1.5rem 1.5rem 0
    }

    .ft-form {
      background: rgba(24, 38, 64, 0.84);
      border: 1px solid color-mix(in oklab, var(--accent) 30%, transparent);
      border-radius: 8px;
      padding: 1.5rem;
      margin-bottom: 1.5rem
    }

    .ft-form-title {
      font-family: var(--ks-display);
      font-size: .85rem;
      letter-spacing: 3px;
      color: var(--ks-accent-strong);
      margin-bottom: 1rem;
      text-transform: uppercase;
      text-align: center
    }

    .ft-form-row {
      display: flex;
      gap: .75rem;
      flex-wrap: wrap;
      margin-bottom: .75rem
    }

    .ft-form-row .fg {
      flex: 1;
      min-width: 130px
    }

    .ft-chips {
      display: flex;
      gap: .5rem;
      flex-wrap: wrap;
      margin-bottom: .75rem
    }

    .ft-chip {
      padding: 7px 16px;
      border-radius: 20px;
      font-size: .65rem;
      font-weight: 700;
      letter-spacing: 1.5px;
      text-transform: uppercase;
      cursor: pointer;
      border: 1px solid rgba(255, 255, 255, 0.12);
      background: rgba(255, 255, 255, 0.03);
      color: var(--muted);
      transition: all .2s
    }

    .ft-chip.active,
    .ft-chip:hover {
      background: color-mix(in oklab, var(--accent) 15%, transparent);
      border-color: color-mix(in oklab, var(--accent) 50%, transparent);
      color: var(--ks-accent-strong)
    }

    .ft-results-header {
      display: flex;
      justify-content: space-between;
      align-items: center;
      margin-bottom: 1rem;
      padding: 0 .25rem
    }

    .ft-results-count {
      font-size: .7rem;
      color: var(--muted);
      letter-spacing: 1px
    }

    .ft-results-grid {
      display: grid;
      grid-template-columns: 1fr;
      gap: .75rem;
      padding-bottom: 3rem
    }

    .ft-card {
      background: rgba(18, 31, 54, 0.94);
      border: 1px solid rgba(255, 255, 255, 0.11);
      border-radius: 8px;
      padding: 1.25rem;
      transition: all .28s;
      display: flex;
      gap: 1rem;
      align-items: flex-start;
      box-shadow: 0 4px 18px rgba(0, 0, 0, 0.45)
    }

    .ft-card:hover {
      border-color: color-mix(in oklab, var(--accent) 40%, transparent);
      transform: translateY(-2px);
      box-shadow: 0 10px 30px rgba(0, 0, 0, 0.6)
    }

    .ft-card-icon {
      width: 48px;
      height: 48px;
      border-radius: 8px;
      flex-shrink: 0;
      display: flex;
      align-items: center;
      justify-content: center;
      font-size: 1.4rem;
      background: color-mix(in oklab, var(--accent) 10%, transparent);
      border: 1px solid color-mix(in oklab, var(--accent) 25%, transparent)
    }

    .ft-card-body {
      flex: 1;
      min-width: 0
    }

    .ft-card-name {
      font-family: var(--ks-display);
      font-size: .9rem;
      font-weight: 700;
      color: var(--white);
      letter-spacing: .5px;
      margin-bottom: .3rem
    }

    .ft-card-meta {
      font-size: .72rem;
      color: var(--muted);
      margin-bottom: .15rem
    }

    .ft-card-desc {
      font-size: .75rem;
      color: var(--dim);
      margin-top: .4rem;
      line-height: 1.5
    }

    .ft-card-right {
      display: flex;
      flex-direction: column;
      align-items: flex-end;
      gap: .4rem;
      flex-shrink: 0
    }

    .ft-card-distance {
      font-family: var(--ks-display);
      font-size: .9rem;
      color: var(--ks-accent-strong);
      font-weight: 700;
      white-space: nowrap
    }

    .ft-card-distance-label {
      font-size: .55rem;
      color: var(--dim);
      letter-spacing: 1px;
      text-transform: uppercase
    }

    .ft-org-badge {
      display: inline-block;
      padding: 3px 10px;
      border-radius: 3px;
      font-size: .55rem;
      font-weight: 800;
      letter-spacing: 1.5px;
      text-transform: uppercase
    }

    .ft-org-aau {
      background: color-mix(in oklab, var(--accent) 20%, transparent);
      color: var(--ks-accent-strong);
      border: 1px solid color-mix(in oklab, var(--accent) 30%, transparent)
    }

    .ft-org-wkf {
      background: rgba(52, 152, 219, 0.2);
      color: #5dade2;
      border: 1px solid rgba(52, 152, 219, 0.3)
    }

    .ft-org-usa {
      background: rgba(60, 179, 113, 0.15);
      color: #3cb371;
      border: 1px solid rgba(60, 179, 113, 0.25)
    }

    .ft-org-naska {
      background: rgba(241, 148, 138, 0.15);
      color: #F1948A;
      border: 1px solid rgba(241, 148, 138, 0.3)
    }

    .ft-org-ikf {
      background: rgba(240, 178, 122, 0.15);
      color: #F0B27A;
      border: 1px solid rgba(240, 178, 122, 0.3)
    }

    .ft-org-wkc {
      background: rgba(93, 173, 226, 0.15);
      color: #7EC8E3;
      border: 1px solid rgba(93, 173, 226, 0.3)
    }

    .ft-org-open {
      background: rgba(255, 255, 255, 0.06);
      color: var(--muted);
      border: 1px solid rgba(255, 255, 255, 0.15)
    }

    .ft-org-other {
      background: rgba(187, 143, 206, 0.15);
      color: #BB8FCE;
      border: 1px solid rgba(187, 143, 206, 0.3)
    }



/* ══════════════════════════════════════════════════════════════════════
   dojo-event-card-base.v1.css
   ══════════════════════════════════════════════════════════════════════ */
    /* Event card — used for tournaments & seminars */
    .event-card {
      background: rgba(14, 24, 46, 0.96);
      border: 1px solid rgba(255, 255, 255, 0.12);
      border-radius: 12px;
      padding: 1.5rem 1.6rem;
      transition: all .3s;
      box-shadow: 0 6px 24px rgba(0, 0, 0, 0.5);
      margin-bottom: 1rem
    }



    .event-card:hover {
      border-color: color-mix(in oklab, var(--accent) 35%, transparent);
      box-shadow: 0 12px 36px rgba(0, 0, 0, 0.65);
      transform: translateY(-4px);
    }

    .event-card.card-next {
      border-color: color-mix(in oklab, var(--accent) 70%, transparent);
      box-shadow: 0 0 0 2px color-mix(in oklab, var(--accent) 18%, transparent), 0 10px 36px rgba(0, 0, 0, 0.6);
      animation: nextCardPulse 4s ease-in-out infinite;
    }

    @keyframes nextCardPulse {

      0%,
      100% {
        box-shadow: 0 0 0 2px color-mix(in oklab, var(--accent) 18%, transparent), 0 10px 36px rgba(0, 0, 0, 0.6);
      }

      50% {
        box-shadow: 0 0 0 4px color-mix(in oklab, var(--accent) 25%, transparent), 0 12px 40px rgba(0, 0, 0, 0.65);
      }
    }

    @media (prefers-reduced-motion: reduce) {
      .event-card.card-next {
        animation: none;
      }
    }

    .card-next-badge {
      display: inline-flex;
      align-items: center;
      gap: .4rem;
      font-family: var(--ks-display);
      font-size: .6rem;
      letter-spacing: 2px;
      text-transform: uppercase;
      color: var(--ks-accent-strong);
      background: color-mix(in oklab, var(--accent) 12%, transparent);
      border: 1px solid color-mix(in oklab, var(--accent) 35%, transparent);
      border-radius: 20px;
      padding: 3px 10px;
      margin-bottom: .75rem
    }

    .event-card-icon {
      font-size: 1.8rem;
      margin-bottom: .6rem
    }

    .event-card-name {
      font-family: var(--ks-display);
      font-size: 1.15rem;
      font-weight: 700;
      color: var(--white);
      letter-spacing: .5px;
      margin-bottom: .4rem
    }

    .event-card-meta {
      font-size: .88rem;
      color: var(--muted);
      margin-bottom: .2rem;
      line-height: 1.7
    }

    .event-card-meta span {
      color: var(--text)
    }

    .event-card-desc {
      font-size: .88rem;
      color: var(--dim);
      margin-top: .5rem;
      line-height: 1.6
    }

    .event-card-actions {
      display: flex;
      flex-wrap: wrap;
      gap: .5rem;
      align-items: center;
      justify-content: center;
      margin-top: .9rem
    }



/* ══════════════════════════════════════════════════════════════════════
   dojo-rules-page-typography.v1.css
   ══════════════════════════════════════════════════════════════════════ */
    /* Rules page */
    .rules-badge-label {
      font-size: .75rem
    }

    .rules-badge-title {
      font-size: 1.1rem
    }

    .rules-badge-sub {
      font-size: .85rem
    }

    .rules-badge-count span {
      font-size: .78rem
    }

    .rules-filter-btn {
      font-size: .78rem
    }

    .rules-table th {
      font-size: .75rem
    }

    .rc-cat,
    .rc-aau,
    .rc-nkf {
      font-size: .9rem
    }

    .rc-cat {
      font-size: .78rem
    }

    .rc-cat-title {
      font-size: .88rem
    }

    .rc-tag {
      font-size: .68rem
    }

    .re-cell {
      font-size: .9rem
    }

    .re-cell strong {
      font-size: .82rem
    }

    .rules-edit-btn {
      font-size: .72rem
    }

    .rules-edit-note {
      font-size: .82rem
    }

    .rules-restore-bar {
      font-size: .85rem
    }

    .rules-restore-bar button {
      font-size: .75rem
    }

    .rules-add-btn {
      font-size: .78rem
    }

    .rules-add-form label {
      font-size: .75rem
    }

    .rules-add-form input,
    .rules-add-form select,
    .rules-add-form textarea {
      font-size: .9rem
    }

    .raf-status-btn {
      font-size: .75rem
    }


/* ══════════════════════════════════════════════════════════════════════
   dojo-tournament-page-light-layout-overrides.v1.css
   ══════════════════════════════════════════════════════════════════════ */
    /* ── TOURNAMENT INFO & VIDEOS OVERRIDES ── */
    /* The page canvas follows the theme. These were a fixed light value, so any
       of these views not separately restyled rendered as a white slab for a
       reader whose system is dark. .page-navy-header below is deliberately left
       dark in both themes: it is a brand band like the footer, not a surface. */
    /* No min-height here. The body is a flex column and .view.active grows
       into it, so a view that reaches the bottom of a short page does it
       without pushing the footer a whole viewport further down. See
       dojo-global-document-view-shell.v1.css. */
    #view-find-tournaments,
    #view-tournaments,
    #view-fighters {
      background: var(--ks-canvas);
      padding: 0;
    }

    /* nav restored for find-tournaments */

    /* ── UNIFIED PAGE LAYOUT: Navy Header + Light Content ──────────────── */
    #view-tournament-detail,
    #view-fighter-detail,
    #view-schedule {
      background: var(--ks-canvas);
    }

    .page-navy-header {
      background: #020617;
      padding: 0 0 2.5rem;
      position: relative;
    }

    .page-navy-header .breadcrumb {
      background: transparent;
      border-bottom-color: rgba(255, 255, 255, 0.06);
    }

    .page-navy-header .page-hdr {
      background: transparent;
      padding: 1.2rem 1.5rem 0;
    }

    /* No negative top margin. It existed to tuck this under .page-navy-header,
       whose foot was empty padding; against the band the same 16px pulls the
       first row of content up across the boundary, and the first row on a
       competitor's profile is the tab list -- transparent, so every label was
       sliced in half, dark ink over a dark band on top and light below.

       A band ends where it ends. Content starts under it with its own space. */
    .page-light-content {
      max-width: 900px;
      margin: 0 auto;
      padding: clamp(1.25rem, 3vw, 2rem) 1.5rem 3rem;
      position: relative;
      z-index: 5;
    }

    .page-light-content.wide {
      max-width: 1200px;
    }

    /* Tournament Year spacing polish */
    #view-tournaments .ti-content-wrap {
      padding-top: 0.5rem;
    }


/* ══════════════════════════════════════════════════════════════════════
   dojo-schedule-calendar-shell.v1.css
   ══════════════════════════════════════════════════════════════════════ */
    /* ── 9. CALENDAR CARD ON LIGHT BG ──────────────────────────────── */
    #view-schedule .home-calendar {
      box-shadow:
        0 4px 16px rgba(15, 23, 42, 0.06),
        0 12px 40px rgba(15, 23, 42, 0.04),
        0 0 0 1px color-mix(in oklab, var(--accent) 8%, transparent);
      transition: box-shadow .3s ease;
    }

    #view-schedule .home-calendar:hover {
      box-shadow:
        0 8px 28px rgba(15, 23, 42, 0.08),
        0 16px 48px rgba(15, 23, 42, 0.05),
        0 0 0 1px color-mix(in oklab, var(--accent) 14%, transparent);
    }

    /* ══════════════════════════════════════════════════════════════════
       SCHEDULE PAGE — PREMIUM LIGHT-THEME REDESIGN
       CSS-only visual overrides. No functionality changes.
       ══════════════════════════════════════════════════════════════════ */

    /* ── Calendar card shell ─────────────────────────────────────── */
    #view-schedule .home-calendar {
      background: #FFFFFF;
      border: 1px solid #E2E8F0;
      border-radius: 16px;
      box-shadow:
        0 1px 3px rgba(15, 23, 42, 0.04),
        0 4px 16px rgba(15, 23, 42, 0.05),
        0 0 0 1px color-mix(in oklab, var(--accent) 6%, transparent);
      padding: 1.25rem 1.25rem 1.1rem;
    }

    /* ── Calendar header ─────────────────────────────────────────── */
    #view-schedule .home-calendar-header {
      margin-bottom: 0;
      flex-direction: column;
      align-items: stretch;
    }

    #view-schedule .home-calendar-title {
      color: #0F172A;
      font-size: .85rem;
      letter-spacing: 2.5px;
    }

    #view-schedule .home-calendar-sub {
      color: #64748B;
      font-size: .74rem;
    }



/* ══════════════════════════════════════════════════════════════════════
   dojo-schedule-mini-calendar.v1.css
   ══════════════════════════════════════════════════════════════════════ */
    #view-schedule .sch-month-nav {
      display: flex;
      align-items: center;
      justify-content: center;
      gap: .5rem;
      margin: 0 0 .6rem;
      padding-bottom: .7rem;
      border-bottom: 1px solid #E2E8F0;
    }

    /* Month label */
    #view-schedule #sch-cal-month {
      color: var(--ks-accent-strong) !important;
      font-family: var(--ks-display);
      font-size: .82rem;
      letter-spacing: 2px;
      min-width: 120px;
      text-align: center;
    }

    /* Nav buttons (‹ ›) */
    #view-schedule .sch-month-nav .btn.btn-ghost {
      background: #F4F6FB;
      border: 1px solid #E2E8F0;
      color: #0F172A;
      border-radius: var(--ks-r-control);
      min-width: 34px;
      min-height: 34px;
      font-size: 1.1rem;
      /* Named properties, matching .btn in dojo-global-button-system.v1.css —
         these month-nav buttons are `#view-schedule .btn`, so they take the
         schedule focus ring and `all` would fade it in. */
      transition-property: background, border-color, color, box-shadow, transform, filter, opacity;
      transition-duration: .22s;
      transition-timing-function: ease;
    }

    #view-schedule .sch-month-nav .btn.btn-ghost:hover {
      background: #E2E8F0;
      border-color: color-mix(in oklab, var(--accent) 30%, transparent);
      color: var(--ks-accent-strong);
    }

    /* Clear selection button */
    #view-schedule .sch-clear-btn {
      display: none;
      align-items: center;
      justify-content: center;
      gap: .35rem;
      margin: .5rem 0 0;
      padding: 6px 14px;
      border: 1px solid #E2E8F0;
      border-radius: var(--ks-r-control);
      background: #F7F8FC;
      color: #64748B;
      font-size: .68rem;
      font-weight: 600;
      letter-spacing: .6px;
      cursor: pointer;
      transition: all .22s ease;
      width: 100%;
    }

    #view-schedule .sch-clear-btn.visible {
      display: flex;
    }

    #view-schedule .sch-clear-btn:hover {
      background: #E2E8F0;
      color: var(--ks-accent-strong);
      border-color: color-mix(in oklab, var(--accent) 30%, transparent);
    }

    /* ── Mini calendar grid container ────────────────────────────── */
    #view-schedule .home-calendar-mini {
      background: #F7F8FC;
      border: 1px solid #E2E8F0;
      border-radius: 12px;
      padding: .9rem;
    }

    /* ── Weekday labels ──────────────────────────────────────────── */
    #view-schedule .home-calendar-mini-weekday {
      color: #64748B;
      font-size: .58rem;
      font-weight: 700;
      letter-spacing: 1px;
    }

    /* ── Day cells ────────────────────────────────────────────────── */
    #view-schedule .home-calendar-mini-cell {
      background: #FFFFFF;
      color: #0F172A;
      border: 1px solid transparent;
      border-radius: 10px;
      min-height: 36px;
      font-size: .74rem;
      font-weight: 500;
      transition: all .2s ease;
      cursor: pointer;
    }

    #view-schedule .home-calendar-mini-cell:hover:not([disabled]) {
      background: #F4F6FB;
      border-color: #E2E8F0;
    }

    #view-schedule .home-calendar-mini-cell.other-month {
      background: transparent;
      color: #CBD5E1;
    }

    /* Today */
    #view-schedule .home-calendar-mini-cell.today {
      background: rgba(240, 220, 154, 0.22);
      border-color: color-mix(in oklab, var(--accent) 35%, transparent);
      color: #0F172A;
      font-weight: 700;
    }

    /* Selected day */
    #view-schedule .home-calendar-mini-cell.selected {
      background: var(--ks-accent);
      border-color: var(--ks-accent);
      color: var(--ks-on-accent);
      font-weight: 700;
      box-shadow: 0 2px 8px color-mix(in oklab, var(--accent) 30%, transparent), 0 0 0 2px color-mix(in oklab, var(--accent) 12%, transparent);
    }

    #view-schedule .home-calendar-mini-cell.selected .home-calendar-mini-dot {
      background: #FFFFFF;
    }

    /* Event dot */
    #view-schedule .home-calendar-mini-dot {
      background: var(--ks-accent);
      width: 5px;
      height: 5px;
    }


/* ══════════════════════════════════════════════════════════════════════
   dojo-schedule-event-list.v1.css
   ══════════════════════════════════════════════════════════════════════ */
    #view-schedule .home-calendar-main {
      min-width: 0;
      display: flex;
      flex-direction: column;
      gap: .65rem;
    }

    /* Panel header (date headline + count) */
    #view-schedule .sch-panel-header {
      display: flex;
      align-items: center;
      justify-content: space-between;
      padding: .55rem .7rem;
      background: #F7F8FC;
      border: 1px solid #E2E8F0;
      border-radius: 10px;
    }

    #view-schedule .sch-panel-date {
      font-family: var(--ks-display);
      font-size: .78rem;
      font-weight: 700;
      color: #0F172A;
      letter-spacing: 1px;
    }

    #view-schedule .sch-panel-count {
      font-size: .6rem;
      font-weight: 700;
      letter-spacing: .8px;
      text-transform: uppercase;
      color: var(--ks-accent-strong);
      background: color-mix(in oklab, var(--accent) 8%, transparent);
      border: 1px solid color-mix(in oklab, var(--accent) 20%, transparent);
      border-radius: 20px;
      padding: 2px 10px;
    }

    #view-schedule .home-calendar-list {
      gap: .75rem;
      display: flex;
      flex-direction: column;
    }

    #view-schedule .home-calendar-item {
      background: #FFFFFF;
      border: 1px solid #E2E8F0;
      border-radius: 12px;
      padding: .85rem .95rem;
      box-shadow: 0 1px 3px rgba(15, 23, 42, 0.03);
      transition: all .22s ease;
    }

    /* Tournament gold accent border */
    #view-schedule .home-calendar-item.sch-tournament {
      border-left: 3px solid var(--ks-accent);
    }

    #view-schedule .home-calendar-item:hover {
      border-color: color-mix(in oklab, var(--accent) 30%, transparent);
      box-shadow: 0 4px 16px rgba(15, 23, 42, 0.06), 0 0 0 1px color-mix(in oklab, var(--accent) 8%, transparent);
    }

    /* Date badge */
    #view-schedule .home-calendar-date {
      background: #F7F8FC;
      border: 1px solid #E2E8F0;
      border-radius: 10px;
    }

    #view-schedule .home-calendar-date-mon {
      color: var(--ks-accent-strong);
    }

    #view-schedule .home-calendar-date-day {
      color: #0F172A;
    }

    /* Event name + meta */
    #view-schedule .home-calendar-name {
      color: #0F172A;
      font-size: 1rem;
      font-weight: 800;
    }

    #view-schedule .home-calendar-meta {
      color: #475569;
      font-size: .82rem;
      font-weight: 600;
    }

    /* Badges */
    #view-schedule .home-calendar-badge-reminder {
      background: color-mix(in oklab, var(--accent) 10%, transparent);
      color: var(--ks-accent-strong);
      border-color: color-mix(in oklab, var(--accent) 25%, transparent);
      font-size: .62rem;
    }

    #view-schedule .home-calendar-badge-today {
      background: rgba(60, 179, 113, 0.08);
      color: #2E8B57;
      border-color: rgba(60, 179, 113, 0.2);
      font-size: .62rem;
    }

    /* ── Reminder card ───────────────────────────────────────────── */
    #view-schedule .home-calendar-reminder {
      background: linear-gradient(135deg, rgba(72, 143, 229, 0.06) 0%, #FFFFFF 100%);
      border: 1px solid rgba(93, 173, 226, 0.2);
      border-left: 3px solid #5DADE2;
      border-radius: 12px;
      box-shadow: 0 2px 12px rgba(52, 152, 219, 0.06);
    }

    #view-schedule .home-calendar-reminder::before {
      background: linear-gradient(90deg, rgba(93, 173, 226, 0.3), transparent);
    }

    #view-schedule .home-calendar-reminder-kicker {
      color: #3B82F6;
    }

    #view-schedule .home-calendar-reminder-name {
      color: #0F172A;
    }

    #view-schedule .home-calendar-reminder-meta {
      color: #475569;
    }

    /* ── Empty state ─────────────────────────────────────────────── */
    #view-schedule .home-calendar-empty {
      border: 1px dashed #E2E8F0;
      color: #94A3B8;
      background: #FAFBFE;
      border-radius: 12px;
      padding: 2rem 1rem;
      font-size: .78rem;
      text-align: center;
      line-height: 1.7;
    }

    #view-schedule .home-calendar-empty::before {
      content: '📅';
      display: block;
      font-size: 1.5rem;
      margin-bottom: .4rem;
      opacity: .6;
    }


/* ══════════════════════════════════════════════════════════════════════
   dojo-schedule-responsive.v1.css
   ══════════════════════════════════════════════════════════════════════ */
    @media (min-width: 1024px) {
      #view-schedule .page-light-content {
        /* The page's own measure, like every other screen. It was held at
           1100px, narrower than the band above it, so the content read as a
           column dropped onto a wider page. */
        max-width: var(--ks-measure);
      }

      #view-schedule .home-calendar-layout {
        /* The date picker is a rail, not a column. It is one control about 300px
           tall next to a list that runs for a couple of thousand, and as an
           ordinary grid cell it left the whole left side of the page empty
           below itself -- on this dojo, a thousand pixels of it.

           align-items: start stops the cell stretching, and sticky keeps the
           picker beside whatever part of the list the reader has scrolled to,
           which is the behaviour a date picker for a long list wants anyway. */
        grid-template-columns: 320px minmax(0, 1fr);
        gap: clamp(1.25rem, 2.5vw, 2rem);
        align-items: start;
      }

      #view-schedule .home-calendar-mini {
        position: sticky;
        top: calc(var(--ks-nav-h) + 1.25rem);
      }
    }

    /* Following the scroll is a convenience, not information. Somebody who has
       asked for less movement gets the rail where it was drawn. */
    @media (prefers-reduced-motion: reduce) {
      #view-schedule .home-calendar-mini {
        position: static;
      }
    }

    /* ── Tablet (768–1023px) ──────────────────────────────────────── */
    @media (min-width: 768px) and (max-width: 1023px) {
      #view-schedule .page-light-content {
        max-width: 780px;
        padding: 0 1.25rem 2.5rem;
      }

      #view-schedule .home-calendar-layout {
        grid-template-columns: 260px minmax(0, 1fr);
        gap: 1rem;
      }

      #view-schedule .home-calendar {
        padding: 1.1rem;
      }
    }

    /* ── Mobile (<768px) ─────────────────────────────────────────── */
    @media (max-width: 767px) {
      #view-schedule .page-light-content {
        padding: 0 .85rem 2rem;
        margin-top: -.35rem;
      }

      #view-schedule .home-calendar {
        padding: .9rem;
        border-radius: 14px;
      }

      #view-schedule .home-calendar-header {
        margin-bottom: .75rem;
      }

      #view-schedule .home-calendar-title {
        font-size: .78rem;
        letter-spacing: 2px;
      }

      #view-schedule .home-calendar-layout {
        grid-template-columns: 1fr;
        gap: .85rem;
      }

      #view-schedule .home-calendar-mini {
        padding: .75rem;
      }

      #view-schedule .home-calendar-mini-cell {
        min-height: 38px;
        font-size: .72rem;
      }

      #view-schedule .home-calendar-item {
        padding: .75rem .8rem;
      }

      #view-schedule .btn {
        min-height: 44px;
      }

      #view-schedule .sch-quick-links-grid {
        grid-template-columns: 1fr 1fr;
      }

      #view-schedule .sch-quick-link {
        min-height: 44px;
        font-size: .66rem;
      }

      #view-schedule .sch-panel-header {
        padding: .45rem .6rem;
      }

      #view-schedule .sch-panel-date {
        font-size: .72rem;
      }
    }


/* ══════════════════════════════════════════════════════════════════════
   dojo-schedule-actions-base.v1.css
   ══════════════════════════════════════════════════════════════════════ */
    #view-schedule .sch-action-link {
      display: inline-flex;
      align-items: center;
      padding: 5px 12px;
      border-radius: 8px;
      font-size: .65rem;
      font-weight: 700;
      letter-spacing: .8px;
      text-transform: uppercase;
      text-decoration: none;
      cursor: pointer;
      transition: all .22s ease;
    }

    #view-schedule .sch-action-register {
      background: var(--ks-accent);
      color: var(--ks-on-accent);
      border: 1px solid var(--ks-accent);
    }

    #view-schedule .sch-action-register:hover {
      background: var(--ks-accent);
      border-color: var(--ks-accent);
      box-shadow: 0 2px 10px color-mix(in oklab, var(--accent) 30%, transparent);
    }

    #view-schedule .sch-action-flyer,
    #view-schedule .sch-action-info {
      background: transparent;
      color: #64748B;
      border: 1px solid #E2E8F0;
    }

    #view-schedule .sch-action-flyer:hover,
    #view-schedule .sch-action-info:hover {
      border-color: color-mix(in oklab, var(--accent) 35%, transparent);
      color: var(--ks-accent-strong);
      background: color-mix(in oklab, var(--accent) 4%, transparent);
    }

    @media (max-width: 767px) {
      #view-schedule .sch-action-link {
        min-height: 36px;
        padding: 6px 14px;
        font-size: .62rem;
      }
    }


/* ══════════════════════════════════════════════════════════════════════
   dojo-schedule-reduced-motion.v1.css
   ══════════════════════════════════════════════════════════════════════ */
    @media (prefers-reduced-motion: reduce) {

      #view-schedule .home-calendar,
      #view-schedule .home-calendar-item,
      #view-schedule .home-calendar-mini-cell,
      #view-schedule .sch-month-nav .btn.btn-ghost,
      #view-schedule .sch-quick-links a {
        transition: none !important;
      }
    }


/* ══════════════════════════════════════════════════════════════════════
   dojo-schedule-quicklinks-base.v1.css
   ══════════════════════════════════════════════════════════════════════ */
    /* Panel on the shared surface tokens — the links inside already take
       theirs from dojo-schedule-shell.v1.css, and a hardcoded white box was
       the one piece of this panel dark mode could not reach. */
    #view-schedule .sch-quick-links {
      background: var(--ks-surface);
      border: 1px solid var(--ks-line);
      border-radius: 12px;
      padding: .85rem;
      box-shadow: 0 1px 3px rgba(15, 23, 42, 0.03);
    }

    #view-schedule .sch-quick-links-title {
      font-family: var(--ks-display);
      font-size: .7rem;
      font-weight: 700;
      color: var(--ks-ink);
      letter-spacing: 2px;
      text-transform: uppercase;
      margin-bottom: .6rem;
      padding-bottom: .45rem;
      border-bottom: 1px solid var(--ks-line-soft, var(--ks-line));
    }

    #view-schedule .sch-quick-links-grid {
      display: grid;
      grid-template-columns: 1fr 1fr;
      gap: .4rem;
    }

    /* The links are conditional (team doors, hotel), so the count runs 3-6.
       An odd count leaves a half-empty last row; the last link taking the
       full row keeps the grid balanced at every legitimate count. */
    #view-schedule .sch-quick-link:last-child:nth-child(odd) {
      grid-column: 1 / -1;
    }

    #view-schedule .sch-quick-link {
      display: flex;
      align-items: center;
      gap: .4rem;
      padding: .5rem .6rem;
      border-radius: 8px;
      border: 1px solid #F1F5F9;
      background: #FAFBFE;
      color: #334155;
      font-size: .68rem;
      font-weight: 600;
      text-decoration: none;
      cursor: pointer;
      transition: all .2s ease;
      min-height: 40px;
    }

    #view-schedule .sch-quick-link:hover {
      background: color-mix(in oklab, var(--accent) 6%, transparent);
      border-color: color-mix(in oklab, var(--accent) 30%, transparent);
      color: var(--ks-accent-strong);
    }

    #view-schedule .sch-quick-link-icon {
      font-size: .85rem;
      line-height: 1;
      flex-shrink: 0;
    }


/* ══════════════════════════════════════════════════════════════════════
   dojo-schedule-focus-visible.v1.css
   ══════════════════════════════════════════════════════════════════════ */
    #view-schedule .home-calendar-mini-cell:focus-visible,
    #view-schedule .btn:focus-visible,
    #view-schedule .sch-action-link:focus-visible,
    #view-schedule .sch-quick-link:focus-visible,
    #view-schedule .sch-clear-btn:focus-visible {
      outline: 2px solid var(--ks-accent);
      outline-offset: 2px;
      box-shadow: 0 0 0 4px color-mix(in oklab, var(--accent) 15%, transparent);
    }


/* ══════════════════════════════════════════════════════════════════════
   dojo-schedule-event-actions-base.v1.css
   ══════════════════════════════════════════════════════════════════════ */
    #view-schedule .sch-event-actions {
      display: flex;
      gap: .4rem;
      flex-wrap: wrap;
      margin-top: .55rem;
      padding-top: .5rem;
      border-top: 1px solid #F1F5F9;
    }


/* ══════════════════════════════════════════════════════════════════════
   dojo-tournament-info-shell.v1.css
   ══════════════════════════════════════════════════════════════════════ */
    .ti-hero-wrap {
      background: #020617;
      color: #FFF;
      padding: 4rem 1.5rem 6rem;
      margin-bottom: -3rem;
      position: relative;
      overflow: hidden;
      background-image:
        radial-gradient(ellipse at 50% 0%, color-mix(in oklab, var(--accent) 6%, transparent) 0%, transparent 60%),
        radial-gradient(ellipse at 80% 30%, rgba(30, 64, 175, 0.04) 0%, transparent 50%);
    }

    .ti-hero-wrap::after {
      content: '';
      position: absolute;
      bottom: 0;
      left: 5%;
      right: 5%;
      height: 1px;
      background: linear-gradient(90deg, transparent, color-mix(in oklab, var(--accent) 20%, transparent), transparent);
      pointer-events: none;
    }

    .ti-hero-inner {
      max-width: 1200px;
      margin: 0 auto;
      display: flex;
      justify-content: space-between;
      align-items: center;
      gap: 2rem;
      position: relative;
      z-index: 2;
    }

    .ti-hero-left h5 {
      color: var(--ks-accent-strong);
      font-family: var(--ks-display);
      font-size: .8rem;
      font-weight: 800;
      letter-spacing: 2.5px;
      text-transform: uppercase;
      margin: 0 0 .5rem 0;
    }

    .ti-hero-left h1 {
      font-family: var(--ks-display);
      font-weight: 900;
      font-size: 3.5rem;
      color: #FFF;
      line-height: 1.1;
      margin: 0 0 .5rem 0;
      letter-spacing: 1px;
      text-shadow: 0 2px 12px rgba(0, 0, 0, 0.3);
    }

    .ti-hero-left p {
      color: #94A3B8;
      font-size: 1rem;
      font-weight: 500;
      margin: 0 0 2rem 0;
    }

    .ti-coach-staff {
      border-top: 1px solid rgba(255, 255, 255, 0.1);
      padding-top: 1rem;
      margin-top: 2rem;
    }

    .ti-coach-staff h6 {
      color: var(--ks-accent-strong);
      font-size: .7rem;
      font-weight: 700;
      letter-spacing: 1.5px;
      margin: 0 0 .5rem 0;
      text-transform: uppercase;
    }

    .ti-coach-staff div {
      color: #E2E8F0;
      font-size: .95rem;
      font-weight: 500;
      letter-spacing: 0.5px;
      margin-bottom: .25rem;
      font-family: 'Inter', sans-serif;
    }

    .ti-hero-right {
      text-align: center;
      display: flex;
      flex-direction: column;
      align-items: center;
      position: relative;
    }

    .ti-hero-logo-box {
      position: relative;
      cursor: pointer;
      transition: transform 0.2s;
    }

    .ti-hero-logo-box:hover {
      transform: scale(1.02);
    }

    .ti-hero-logo {
      max-width: 350px;
      border-radius: 4px;
      transition: opacity 0.3s ease;
    }

    .ti-hero-powered {
      font-size: .7rem;
      font-weight: 700;
      color: #94A3B8;
      letter-spacing: 1px;
      text-transform: uppercase;
      margin-top: 1rem;
      border-top: 1px solid rgba(255, 255, 255, 0.1);
      padding-top: 1rem;
      width: 100%;
    }

    .ti-hero-powered a {
      color: var(--ks-accent-strong);
      text-decoration: none;
    }

    .ti-content-wrap {
      max-width: 1200px;
      margin: 0 auto;
      position: relative;
      z-index: 5;
      padding: 0 1.5rem 3rem;
    }

    .ti-section {
      background: #FFF;
      border-radius: 14px;
      padding: 2rem;
      margin-bottom: 2rem;
      box-shadow: 0 4px 20px rgba(0, 0, 0, 0.04), 0 1px 3px rgba(0, 0, 0, 0.03);
      border: 1px solid #E2E8F0;
      border-top: 3px solid color-mix(in oklab, var(--accent) 18%, transparent);
    }

    .ti-section-hdr {
      display: flex;
      align-items: center;
      gap: 1rem;
      margin-bottom: 1.5rem;
      border-bottom: 1px solid #E2E8F0;
      padding-bottom: 1rem;
    }

    .ti-section-hdr svg {
      width: 32px;
      height: 32px;
      color: var(--ks-accent-strong);
    }

    .ti-section-hdr h3 {
      font-family: var(--ks-display);
      font-size: 1.1rem;
      font-weight: 800;
      color: var(--ks-ink);
      margin: 0;
      text-transform: uppercase;
      letter-spacing: 1.5px;
    }

    .ti-section-desc {
      font-size: .9rem;
      color: #64748B;
      font-weight: 500;
      margin: 0;
    }

    .ti-grid-2 {
      display: grid;
      grid-template-columns: 1fr 1fr;
      gap: 1.5rem;
    }

    .ti-card {
      background: #F8FAFC;
      border-radius: 8px;
      padding: 1.5rem;
      border: 1px solid #E2E8F0;
      display: flex;
      align-items: center;
      gap: 1.5rem;
      cursor: pointer;
      text-decoration: none;
      transition: all 0.2s;
      border-left: 6px solid #CBD5E1;
    }

    .ti-card:hover {
      transform: translateY(-3px);
      box-shadow: 0 8px 24px rgba(0, 0, 0, 0.06), 0 0 0 1px color-mix(in oklab, var(--accent) 8%, transparent);
      background: #FFF;
      border-left-color: var(--ks-accent);
    }

    .ti-card-icon {
      width: 50px;
      height: 50px;
      border-radius: 8px;
      display: flex;
      align-items: center;
      justify-content: center;
      flex-shrink: 0;
    }

    .ti-card-icon svg {
      width: 24px;
      height: 24px;
    }

    .ti-card-content {
      flex: 1;
    }

    .ti-card-title {
      font-size: 1.05rem;
      font-weight: 800;
      color: var(--ks-ink);
      margin-bottom: .25rem;
      font-family: 'Inter', sans-serif;
    }

    .ti-card-desc {
      font-size: .85rem;
      color: #64748B;
      font-weight: 500;
      line-height: 1.4;
    }

    .ti-card-arrow {
      width: 36px;
      height: 36px;
      border-radius: 50%;
      background: #0F172A;
      color: #FFF;
      display: flex;
      align-items: center;
      justify-content: center;
      flex-shrink: 0;
    }

    /* AAU's own colour, in a categorical set with .ti-border-blue (NKF) and
       .ti-border-green (Smoothcomp). Not the legacy theme gold, so it does
       not follow the tenant accent — the tenant does not own how a third
       party's mark is identified. */
    .ti-border-gold {
      border-left-color: #F4D03F;
    }

    .ti-bg-gold {
      background: rgba(244, 208, 63, 0.2);
      color: #B9770E;
    }

    .ti-border-blue {
      border-left-color: #3498DB;
    }

    .ti-bg-blue {
      background: rgba(52, 152, 219, 0.15);
      color: #2874A6;
    }

    .ti-border-green {
      border-left-color: #27AE60;
    }

    .ti-bg-green {
      background: rgba(39, 174, 96, 0.15);
      color: #1E8449;
    }

    .ti-border-purple {
      border-left-color: #9B59B6;
    }

    .ti-bg-purple {
      background: rgba(155, 89, 182, 0.15);
      color: #76448A;
    }

    .ti-bottom-banner {
      background: #0F172A;
      color: #FFF;
      border-radius: 12px;
      padding: 2rem;
      display: flex;
      justify-content: space-between;
      align-items: center;
      margin-top: 1rem;
    }

    .ti-bb-left {
      display: flex;
      align-items: center;
      gap: 1rem;
    }

    .ti-bb-left svg {
      color: var(--ks-accent-strong);
      width: 44px;
      height: 44px;
      min-width: 44px;
      min-height: 44px;
    }

    .ti-bb-text h3 {
      font-family: 'Inter', sans-serif;
      font-size: 1.4rem;
      font-weight: 800;
      margin: 0 0 .25rem 0;
    }

    .ti-bb-text p {
      font-size: .95rem;
      color: #94A3B8;
      margin: 0;
    }

    .ti-bb-btn {
      background: linear-gradient(135deg, var(--ks-accent), var(--accent-deep));
      color: var(--ks-on-accent);
      padding: 12px 24px;
      border-radius: var(--ks-r-control-sm);
      font-weight: 800;
      text-decoration: none;
      font-size: .9rem;
      transition: all 0.25s;
      white-space: nowrap;
      box-shadow: 0 4px 12px color-mix(in oklab, var(--accent) 20%, transparent);
    }

    .ti-bb-btn:hover {
      background: linear-gradient(135deg, var(--accent-deep), var(--ks-accent));
      box-shadow: 0 6px 20px color-mix(in oklab, var(--accent) 30%, transparent);
      transform: translateY(-1px);
    }


/* ══════════════════════════════════════════════════════════════════════
   dojo-premium-tournament-seminar-section-shell.v1.css
   ══════════════════════════════════════════════════════════════════════ */
    /* ══════════════════════════════════════════════════════════════════
   PREMIUM TOURNAMENT & SEMINAR CARDS — REDESIGNED
   Scoped to #view-find-tournaments to avoid conflicts
   ══════════════════════════════════════════════════════════════════ */

    /* ── SECTION CONTAINERS ──────────────────────────────────────── */
    .ti-prem-section {
      background: #FFFFFF;
      border-radius: 14px;
      margin-bottom: 2rem;
      box-shadow:
        0 1px 2px rgba(0, 0, 0, 0.04),
        0 4px 16px rgba(0, 0, 0, 0.03),
        0 12px 40px rgba(0, 0, 0, 0.02);
      border: 1px solid rgba(226, 232, 240, 0.8);
      overflow: hidden;
    }

    .ti-prem-hdr {
      display: flex;
      align-items: center;
      gap: 1rem;
      padding: 1.25rem 1.75rem;
      background: linear-gradient(180deg, #FAFBFD 0%, #F6F8FB 100%);
      border-bottom: 1px solid #EDF0F4;
    }

    .ti-prem-hdr-icon {
      width: 44px;
      height: 44px;
      border-radius: 10px;
      display: flex;
      align-items: center;
      justify-content: center;
      flex-shrink: 0;
    }

    .ti-prem-icon-gold {
      background: linear-gradient(135deg, #FEF9E7 0%, #FDE68A 100%);
      border: 1px solid rgba(253, 224, 71, 0.4);
      color: #92400E;
      box-shadow: 0 1px 4px rgba(253, 224, 71, 0.15);
    }

    .ti-prem-icon-gold svg {
      stroke: #92400E;
    }

    .ti-prem-icon-slate {
      background: linear-gradient(135deg, #F1F5F9 0%, #E2E8F0 100%);
      border: 1px solid rgba(203, 213, 225, 0.5);
      color: #334155;
      box-shadow: 0 1px 4px rgba(148, 163, 184, 0.1);
    }

    .ti-prem-icon-slate svg {
      stroke: #334155;
    }

    .ti-prem-hdr-text {
      flex: 1;
      min-width: 0;
    }

    .ti-prem-hdr-text h3 {
      font-family: var(--ks-display);
      font-size: .88rem;
      font-weight: 700;
      color: #0F172A;
      margin: 0;
      letter-spacing: 1.5px;
      line-height: 1.2;
    }

    .ti-prem-hdr-text p {
      font-size: .74rem;
      color: #64748B;
      font-weight: 500;
      margin: .2rem 0 0;
      line-height: 1.4;
    }

    .ti-prem-add-btn {
      white-space: nowrap;
      font-size: .62rem;
      font-weight: 800;
      letter-spacing: 1.2px;
      text-transform: uppercase;
      padding: 8px 18px;
      border-radius: var(--ks-r-control);
      border: none;
      cursor: pointer;
      transition: all .2s cubic-bezier(0.165, 0.84, 0.44, 1);
      flex-shrink: 0;
    }

    .ti-prem-add-gold {
      background: linear-gradient(135deg, #FBBF24 0%, #F59E0B 100%);
      color: #451A03;
      box-shadow: 0 1px 4px rgba(245, 158, 11, 0.25);
    }

    .ti-prem-add-gold:hover {
      transform: translateY(-1px);
      box-shadow: 0 4px 12px rgba(245, 158, 11, 0.35);
      filter: brightness(1.04);
    }

    .ti-prem-add-slate {
      background: linear-gradient(135deg, #1E293B 0%, #0F172A 100%);
      color: #FFF;
      box-shadow: 0 1px 4px rgba(15, 23, 42, 0.2);
    }

    .ti-prem-add-slate:hover {
      transform: translateY(-1px);
      box-shadow: 0 4px 12px rgba(15, 23, 42, 0.3);
      filter: brightness(1.15);
    }

    .ti-prem-body {
      padding: 1.5rem 1.75rem 1.75rem;
    }

    .ti-prem-empty {
      text-align: center;
      padding: 3rem 2rem;
      color: #94A3B8;
      font-size: .8rem;
      font-weight: 500;
      border: 1.5px dashed #E2E8F0;
      border-radius: 12px;
      display: flex;
      flex-direction: column;
      align-items: center;
      gap: .75rem;
      line-height: 1.6;
      background: #FAFBFC;
    }

    .ti-prem-empty-icon {
      width: 48px;
      height: 48px;
      border-radius: 50%;
      background: #F1F5F9;
      border: 1px solid #E2E8F0;
      display: flex;
      align-items: center;
      justify-content: center;
    }


/* ══════════════════════════════════════════════════════════════════════
   dojo-premium-event-card-desktop.v1.css
   ══════════════════════════════════════════════════════════════════════ */
    /* ── EVENT CARD — DESKTOP 2-COLUMN GRID ──────────────────────── */
    #view-find-tournaments .event-card {
      background: #FFFFFF;
      border: 1px solid #E8ECF1;
      color: #0F172A;
      box-shadow:
        0 1px 2px rgba(0, 0, 0, 0.03),
        0 4px 12px rgba(0, 0, 0, 0.03);
      position: relative;
      padding: 0;
      overflow: visible;
      border-radius: 12px;
      display: grid;
      /* One column unless the event actually has travel; an empty sidecar was
         a reserved block of whitespace on every hotel-less event. */
      grid-template-columns: 1fr;
      grid-template-rows: auto;
      transition: box-shadow .3s cubic-bezier(0.165, 0.84, 0.44, 1),
        border-color .3s cubic-bezier(0.165, 0.84, 0.44, 1),
        transform .3s cubic-bezier(0.165, 0.84, 0.44, 1);
    }

    #view-find-tournaments .event-card.has-travel {
      grid-template-columns: 1fr 300px;
    }

    #view-find-tournaments .event-card:hover {
      border-color: color-mix(in oklab, var(--accent) 30%, transparent);
      box-shadow:
        0 1px 2px rgba(0, 0, 0, 0.03),
        0 8px 24px rgba(0, 0, 0, 0.06),
        0 0 0 1px color-mix(in oklab, var(--accent) 8%, transparent);
      transform: translateY(-2px);
    }

    /* Tenant accent, not a fixed amber: the highlighted card belongs to
       whichever dojo is hosting it. */
    #view-find-tournaments .event-card.card-next {
      border-color: color-mix(in oklab, var(--accent) 35%, transparent);
      box-shadow:
        0 1px 2px rgba(0, 0, 0, 0.03),
        0 4px 16px color-mix(in oklab, var(--accent) 10%, transparent);
    }

    #view-find-tournaments .event-card.card-next:hover {
      box-shadow:
        0 1px 2px rgba(0, 0, 0, 0.03),
        0 8px 28px color-mix(in oklab, var(--accent) 14%, transparent),
        0 0 0 1px color-mix(in oklab, var(--accent) 18%, transparent);
    }

    /* Main content area (left column) — target the inline-styled flex wrapper */
    #view-find-tournaments .event-card>div:not(.premium-next-badge):not(.premium-hotel-sub) {
      padding: 1.75rem 2rem;
      grid-column: 1;
      grid-row: 1;
      min-width: 0;
    }

    /* ── EVENT NAME ──────────────────────────────────────────────── */
    .premium-event-name {
      font-size: 1.5rem;
      font-weight: 800;
      color: #0F172A;
      margin-bottom: .5rem;
      line-height: 1.25;
      letter-spacing: -0.3px;
    }

    /* ── EVENT META ROW ──────────────────────────────────────────── */
    /* The card's media row: flyer or icon beside the copy. In a class, not an
       inline style, so the phone tier can restack it -- inline flex styles beat
       every stylesheet and were why the mobile centring rules never won. */
    .premium-event-media {
      display: flex;
      gap: 1.5rem;
      align-items: flex-start;
      flex-wrap: wrap;
    }

    .premium-event-meta {
      font-size: 1rem;
      font-weight: 700;
      color: #475569;
      display: flex;
      align-items: center;
      flex-wrap: wrap;
      /* Spacing between facts comes from the gap, never from inline margins on
         individual items -- which is what lets the row centre cleanly on
         phones and lets any fact be first without a stray indent. */
      gap: .35rem 1rem;
      line-height: 1.7;
    }

    /* ── ORG BADGE ───────────────────────────────────────────────── */
    .premium-org-badge {
      padding: 4px 12px;
      border-radius: 5px;
      font-size: .82rem;
      font-weight: 800;
      text-transform: uppercase;
      color: #FFF;
      letter-spacing: .8px;
      line-height: 1;
    }

    .ft-org-aau {
      /* Amber-700 to amber-800, not amber-500 to amber-600. A gradient is only
         as readable as its lightest stop, and white on #F59E0B is 2.15:1. This
         starts at #B45309 -- 5.02:1 -- so the badge stays an amber pill with a
         white label rather than turning into a different kind of thing. */
      background: linear-gradient(135deg, #B45309 0%, #92400E 100%);
      box-shadow: 0 1px 3px rgba(217, 119, 6, 0.2);
    }

    .ft-org-wkf {
      /* Blue-600 to blue-700, one step down for the same reason: white on
         #3B82F6 is 3.68:1, on #2563EB it is 5.17:1. */
      background: linear-gradient(135deg, #2563EB 0%, #1D4ED8 100%);
      box-shadow: 0 1px 3px rgba(37, 99, 235, 0.2);
    }

    /* ── META ITEMS ──────────────────────────────────────────────── */
    .premium-meta-item {
      display: inline-flex;
      align-items: center;
      gap: 2px;
      color: #475569;
      font-weight: 700;
      font-size: 1rem;
    }

    /* ── EVENT DESCRIPTION ───────────────────────────────────────── */
    .premium-event-desc {
      font-size: 1rem;
      color: #334155;
      margin-top: .75rem;
      line-height: 1.55;
      background: #F8FAFC;
      padding: .75rem 1rem;
      border-radius: 8px;
      border-left: 3px solid #E2E8F0;
      font-weight: 600;
    }

    /* ── ACTION BUTTONS ──────────────────────────────────────────── */
    .premium-event-actions {
      display: flex;
      gap: .6rem;
      margin-top: 1.25rem;
      flex-wrap: wrap;
    }

    .premium-btn {
      font-size: .85rem !important;
      padding: 10px 20px !important;
      font-weight: 700 !important;
      border-radius: var(--ks-r-control)!important;
      display: inline-flex;
      align-items: center;
      gap: .4rem;
      text-decoration: none !important;
      letter-spacing: .5px !important;
      /* Named properties rather than `all`: `all` also animates outline-width,
         so the keyboard focus ring fades in over .2s instead of landing at once.
         The list covers every property the .btn/.btn-gold/.btn-dark/.btn-danger
         hover and :active states actually move, so hover is unchanged.
         !important is load-bearing here: `#view-fighter-detail .btn` and its
         siblings in dojo-unified-page-premium-polish.v1.css set `transition: all`
         at higher specificity and would otherwise put outline back in the list. */
      transition-property: background, border-color, color, box-shadow, transform, filter !important;
      transition-duration: .2s !important;
      transition-timing-function: cubic-bezier(0.165, 0.84, 0.44, 1) !important;
    }

    .premium-btn-outline {
      font-size: .85rem !important;
      padding: 10px 20px !important;
      font-weight: 700 !important;
      border-radius: var(--ks-r-control)!important;
      color: #334155 !important;
      border: 1.5px solid #E2E8F0 !important;
      background: #FFFFFF !important;
      display: inline-flex;
      align-items: center;
      gap: .4rem;
      /* See .premium-btn above: `all` would animate the focus ring's
         outline-width, so the animated properties are named explicitly and
         !important keeps the per-view `transition: all` rules from re-adding it. */
      transition-property: background, border-color, color, box-shadow, transform, filter !important;
      transition-duration: .2s !important;
      transition-timing-function: cubic-bezier(0.165, 0.84, 0.44, 1) !important;
      text-decoration: none !important;
      letter-spacing: .5px !important;
    }

    .premium-btn-outline:hover {
      border-color: #0F172A !important;
      background: #0F172A !important;
      color: #FFF !important;
      transform: translateY(-1px) !important;
      box-shadow: 0 2px 8px rgba(15, 23, 42, 0.15) !important;
    }



/* ══════════════════════════════════════════════════════════════════════
   dojo-premium-hotel-lodging-desktop.v1.css
   ══════════════════════════════════════════════════════════════════════ */
    /* ── HOTEL & LODGING — RIGHT PANEL (DESKTOP) ────────────────── */
    .premium-hotel-sub {
      margin-top: 0;
      border-top: none;
      border-left: 1px solid #EDF0F4;
      padding: 1.75rem 1.5rem;
      background: #FAFBFD;
      border-radius: 0 12px 12px 0;
      grid-column: 2;
      grid-row: 1 / -1;
      display: flex;
      flex-direction: column;
      min-height: 100%;
    }

    .premium-hotel-sub-title {
      font-size: .88rem;
      font-weight: 800;
      color: #334155;
      display: flex;
      justify-content: space-between;
      align-items: center;
      margin-bottom: .75rem;
      letter-spacing: .8px;
      text-transform: uppercase;
      gap: .5rem;
    }

    /* The renderer emits the sprite icon and the real text; no hidden-text
       pseudo-element art. One icon system on this page, not two. */
    .premium-hotel-sub-title span {
      font-size: .88rem;
      font-weight: 800;
      letter-spacing: .8px;
      display: inline-flex;
      align-items: center;
      gap: 6px;
    }

    /* Hotel cards inside the panel */
    .premium-hotel-card {
      background: #FFFFFF;
      border: 1px solid #E8ECF1;
      border-radius: 10px;
      padding: 1rem;
      display: flex;
      gap: 1rem;
      align-items: flex-start;
      margin-bottom: .75rem;
      box-shadow: 0 1px 3px rgba(0, 0, 0, 0.02);
      transition: box-shadow .2s, border-color .2s;
    }

    .premium-hotel-card:hover {
      border-color: #CBD5E1;
      box-shadow: 0 2px 8px rgba(0, 0, 0, 0.04);
    }

    /* Hotel icon plate: the sprite inside comes from the renderer. */
    .premium-hotel-icon {
      background: linear-gradient(135deg, #F1F5F9, #E8ECF1);
      width: 40px;
      height: 40px;
      border-radius: 10px;
      display: flex;
      align-items: center;
      justify-content: center;
      border: 1px solid #E2E8F0;
      flex-shrink: 0;
      position: relative;
    }

    .premium-hotel-name {
      font-size: 1.05rem;
      font-weight: 800;
      color: #0F172A;
      margin-bottom: .2rem;
      line-height: 1.3;
    }

    .premium-hotel-line {
      font-size: .92rem;
      color: #475569;
      margin-bottom: .15rem;
      font-weight: 600;
      line-height: 1.4;
    }

    .premium-hotel-added {
      font-size: .78rem;
      color: #64748B;
      margin-bottom: .5rem;
      margin-top: .35rem;
      font-weight: 700;
      text-transform: uppercase;
      letter-spacing: 1px;
    }

    .premium-hotel-actions {
      display: flex;
      gap: .5rem;
      flex-wrap: wrap;
      margin-top: .5rem;
    }

    .premium-hotel-actions .btn {
      font-size: .78rem !important;
      padding: 6px 14px !important;
      border-radius: var(--ks-r-control-sm)!important;
    }

    .premium-hotel-empty {
      text-align: center;
      color: #64748B;
      font-size: .95rem;
      font-weight: 600;
      padding: 1.5rem 1rem;
      border: 1.5px dashed #E2E8F0;
      border-radius: 10px;
      font-weight: 500;
      background: #FAFBFC;
      flex: 1;
      display: flex;
      align-items: center;
      justify-content: center;
      line-height: 1.5;
    }

    /* Hide empty hotel panel for non-logged-in users */

    /* The panel is a native disclosure now: open on wide screens at render
       time, folded on phones. The summary is the panel's own title. */
    .premium-hotel-sub > .premium-hotel-sub-title {
      cursor: pointer;
      list-style: none;
      user-select: none;
    }

    .premium-hotel-sub > .premium-hotel-sub-title::-webkit-details-marker {
      display: none;
    }

    .premium-hotel-sub > .premium-hotel-sub-title:focus-visible {
      outline: 2px solid var(--ks-focus-ring);
      outline-offset: 2px;
      border-radius: var(--radius-sm);
    }


/* ══════════════════════════════════════════════════════════════════════
   dojo-premium-hotel-photo-thumbnail.v1.css
   ══════════════════════════════════════════════════════════════════════ */
    /* Hotel photo thumbnail — matches tournament flyer size */
    .premium-hotel-photo {
      width: 200px;
      height: 130px;
      object-fit: cover;
      border-radius: 8px;
      margin-bottom: .75rem;
      box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
      flex-shrink: 0;
    }

    .premium-hotel-card.has-photo {
      flex-wrap: wrap;
    }

    .premium-hotel-card.has-photo .premium-hotel-photo {
      flex-basis: auto;
    }


/* ══════════════════════════════════════════════════════════════════════
   dojo-premium-listing-mobile-responsive.v1.css
   ══════════════════════════════════════════════════════════════════════ */
    /* ── MOBILE RESPONSIVE ───────────────────────────────────────── */
    @media (max-width: 800px) {
      #view-find-tournaments .event-card {
        grid-template-columns: 1fr;
      }

      #view-find-tournaments .event-card>div:not(.premium-next-badge):not(.premium-hotel-sub) {
        padding: 1.25rem 1.25rem 1rem;
      }

      .premium-hotel-sub {
        grid-column: 1;
        grid-row: auto;
        border-left: none;
        border-top: 1px solid #EDF0F4;
        border-radius: 0 0 12px 12px;
        padding: 1.25rem;
      }

      .premium-event-name {
        font-size: 1.1rem;
      }

      .premium-event-actions {
        display: grid;
        grid-template-columns: 1fr 1fr;
        gap: .5rem;
      }

      .ti-listing-rsvp-panel {
        max-width: none;
      }

      .premium-event-actions .btn,
      .premium-event-actions .premium-btn,
      .premium-event-actions .premium-btn-outline,
      .premium-event-actions a {
        width: 100%;
        justify-content: center;
        text-align: center;
      }

      .ti-prem-hdr {
        flex-direction: column;
        text-align: center;
        gap: .65rem;
        padding: 1.15rem 1.25rem;
      }

      .ti-prem-add-btn {
        width: 100%;
      }

      .ti-prem-body {
        padding: 1rem 1.25rem 1.25rem;
      }

      /* ── Mobile: one centred card, deliberately ────────────────────────────
       * Two earlier rules meant to centre the flyer and stack the media row,
       * but reached one level too deep and never applied (recorded here on
       * 2026-08-13). The review they were waiting for happened on 2026-08-15
       * against a tenant with a real flyer: the row now stacks and centres via
       * the row's own selector, and every zone of the card follows one
       * alignment on a phone -- identity, facts, description, actions, RSVP.
       * ──────────────────────────────────────────────────────────────── */
      /* The media row: flyer (or icon) above the copy, both centred. */
      #view-find-tournaments .premium-event-media {
        flex-direction: column;
        align-items: center;
      }

      #view-find-tournaments .premium-event-copy {
        width: 100%;
        text-align: center;
      }

      /* Badges are inline-flex, so the copy column's text-align centres them. */

      /* The one RSVP control centres its row: label, segments, note toggle. */
      #view-find-tournaments .ks-rsvp-control-row {
        justify-content: center;
      }

      /* Center event title, meta, description */
      #view-find-tournaments .premium-event-name {
        text-align: center;
      }

      #view-find-tournaments .premium-event-meta {
        justify-content: center;
        text-align: center;
        flex-wrap: wrap;
      }

      #view-find-tournaments .premium-event-desc {
        text-align: center;
        /* On a phone the description is text, not another box. */
        background: none;
        border: 0;
        padding: 0;
      }

      /* Event information leads on a phone; an empty media frame does not.
         Both classes, or the shell's display:flex wins on bundle order. */
      #view-find-tournaments .ks-flyer-thumb.ks-flyer-thumb-empty {
        display: none;
      }

      /* Inside the travel disclosure, hotels are entries, not nested cards. */
      .premium-hotel-card {
        border: 0 !important;
        box-shadow: none !important;
        background: none !important;
        padding: .65rem 0 !important;
        margin-bottom: 0 !important;
        border-bottom: 1px solid #EDF0F4 !important;
        border-radius: 0 !important;
      }

      .premium-hotel-card:last-child {
        border-bottom: 0 !important;
      }

      /* Center action buttons */
      #view-find-tournaments .premium-event-actions {
        justify-items: center;
      }

      /* ── Mobile: Hotel section — center everything ─────────── */

      /* Hotel photo — center + scale */
      .premium-hotel-photo {
        width: 100% !important;
        max-width: 280px !important;
        height: auto !important;
        max-height: 180px !important;
        margin: 0 auto .75rem !important;
        display: block !important;
      }

      /* Hotel card — stack vertically + center content */
      .premium-hotel-card {
        flex-direction: column !important;
        align-items: center !important;
        text-align: center !important;
      }

      /* Hide bell icon on mobile to reduce clutter */
      .premium-hotel-icon {
        display: none !important;
      }

      /* Center hotel text */
      .premium-hotel-name {
        text-align: center !important;
      }

      .premium-hotel-line {
        text-align: center !important;
      }

      .premium-hotel-added {
        text-align: center !important;
      }

      /* Center hotel action buttons */
      .premium-hotel-actions {
        justify-content: center !important;
      }

      /* Center "Hotel & Lodging" header */
      .premium-hotel-sub-title {
        justify-content: center !important;
      }

      /* RSVP panel full width */
      .ti-listing-rsvp-panel {
        max-width: none;
        text-align: center;
      }
    }

    @media (max-width: 480px) {
      .premium-event-actions {
        grid-template-columns: 1fr;
      }

      .premium-event-meta {
        flex-direction: column;
        align-items: center;
        gap: .25rem;
      }

      .premium-event-name {
        font-size: 1rem;
      }
    }


/* ══════════════════════════════════════════════════════════════════════
   dojo-tournament-info-dark-shell-cards.v1.css
   ══════════════════════════════════════════════════════════════════════ */
    /* ══════════════════════════════════════════════════════════════════
       TOURNAMENT-INFO — DARK NAVY / GOLD GLASS CARD THEME
       Scoped ONLY to #view-find-tournaments.
       Placed AFTER all base styles for correct CSS cascade.
       Page background, hero, header, footer are NOT touched.
       ══════════════════════════════════════════════════════════════════ */

    /* ─── SECTION WRAPPERS (deep dark parents) ─────────────────── */
    #view-find-tournaments .ti-section,
    #view-resources .ti-section {
      background: linear-gradient(145deg, #071226, #0F1F3A);
      border: 1px solid color-mix(in oklab, var(--accent) 18%, transparent);
      border-top: 3px solid color-mix(in oklab, var(--accent) 30%, transparent);
      border-radius: 16px;
      box-shadow: 0 18px 50px rgba(0, 0, 0, .35), 0 0 0 1px rgba(0, 0, 0, .12);
    }

    #view-find-tournaments .ti-section-hdr,
    #view-resources .ti-section-hdr {
      border-bottom-color: color-mix(in oklab, var(--accent) 12%, transparent);
    }

    #view-find-tournaments .ti-section-hdr svg,
    #view-resources .ti-section-hdr svg {
      color: var(--ks-accent-strong);
    }

    #view-find-tournaments .ti-section-hdr h3,
    #view-resources .ti-section-hdr h3 {
      color: #FFFFFF;
      font-size: 1.15rem;
      font-weight: 800;
      letter-spacing: .4px;
    }

    #view-find-tournaments .ti-section-desc,
    #view-resources .ti-section-desc {
      color: #94A3B8;
      font-size: .95rem;
      font-weight: 500;
    }

    #view-find-tournaments .ti-section h5,
    #view-resources .ti-section h5 {
      color: var(--ks-accent-strong) !important;
      font-size: .82rem;
      font-weight: 800;
      letter-spacing: 1.5px;
      text-transform: uppercase;
    }

    #view-find-tournaments .ti-prem-section,
    #view-resources .ti-prem-section {
      background: linear-gradient(145deg, #071226, #0F1F3A);
      border: 1px solid color-mix(in oklab, var(--accent) 18%, transparent);
      border-radius: 16px;
      box-shadow: 0 18px 50px rgba(0, 0, 0, .35), 0 0 0 1px rgba(0, 0, 0, .12);
    }

    #view-find-tournaments .ti-prem-hdr,
    #view-resources .ti-prem-hdr {
      background: rgba(15, 23, 42, .5);
      border-bottom-color: color-mix(in oklab, var(--accent) 12%, transparent);
      border-radius: 16px 16px 0 0;
    }

    #view-find-tournaments .ti-prem-hdr-text h3,
    #view-resources .ti-prem-hdr-text h3 {
      color: #FFFFFF;
      font-size: 1.15rem;
      font-weight: 800;
      letter-spacing: .4px;
    }

    #view-find-tournaments .ti-prem-hdr-text p,
    #view-resources .ti-prem-hdr-text p {
      color: #94A3B8;
      font-size: .95rem;
      font-weight: 500;
    }

    #view-find-tournaments .ti-prem-icon-gold,
    #view-resources .ti-prem-icon-gold {
      background: color-mix(in oklab, var(--accent) 12%, transparent);
      border-color: color-mix(in oklab, var(--accent) 25%, transparent);
      border-radius: 12px;
    }

    #view-find-tournaments .ti-prem-icon-gold svg,
    #view-resources .ti-prem-icon-gold svg {
      stroke: var(--ks-accent-strong);
    }

    #view-find-tournaments .ti-prem-icon-slate,
    #view-resources .ti-prem-icon-slate {
      background: rgba(148, 163, 184, .08);
      border-color: rgba(148, 163, 184, .2);
      border-radius: 12px;
    }

    #view-find-tournaments .ti-prem-icon-slate svg,
    #view-resources .ti-prem-icon-slate svg {
      stroke: #94A3B8;
    }

    #view-find-tournaments .ti-prem-empty,
    #view-resources .ti-prem-empty {
      background: rgba(20, 34, 58, .6);
      border-color: color-mix(in oklab, var(--accent) 12%, transparent);
      border-radius: 12px;
      color: #94A3B8;
    }

    #view-find-tournaments .ti-prem-empty-icon,
    #view-resources .ti-prem-empty-icon {
      background: color-mix(in oklab, var(--accent) 6%, transparent);
      border-color: color-mix(in oklab, var(--accent) 15%, transparent);
      border-radius: 12px;
    }

    /* #94A3B8 measured 1.95:1 against this tile — under the 3:1 WCAG 1.4.11
       asks of a graphical object. The markup carries stroke="#CBD5E1", but a
       stylesheet beats a presentation attribute, so this rule is what paints.
       --ink-3 is the same tertiary ink the rest of the platform uses and lands
       at 3.99:1 here. */
    #view-find-tournaments .ti-prem-empty-icon svg rect,
    #view-resources .ti-prem-empty-icon svg rect,
    #view-find-tournaments .ti-prem-empty-icon svg line,
    #view-resources .ti-prem-empty-icon svg line,
    #view-find-tournaments .ti-prem-empty-icon svg path,
    #view-resources .ti-prem-empty-icon svg path,
    #view-find-tournaments .ti-prem-empty-icon svg circle,
    #view-resources .ti-prem-empty-icon svg circle {
      stroke: var(--ink-3);
    }

    /* ─── INNER CLICKABLE CARDS — MEDIUM LIGHTER SLATE ─────────────
       Lighter than parents so they POP visually.
       Consistent 14px radius. Smooth hover lift.
    ─────────────────────────────────────────────────────────────────── */
    #view-find-tournaments .ti-card,
    #view-resources .ti-card {
      background: linear-gradient(145deg, #223A5E, #2A4568);
      border: 1px solid color-mix(in oklab, var(--accent) 22%, transparent);
      border-left: 6px solid color-mix(in oklab, var(--accent) 35%, transparent);
      border-radius: 14px;
      box-shadow:
        inset 0 1px 0 rgba(255, 255, 255, .06),
        0 8px 24px rgba(0, 0, 0, .25);
      transition:
        transform .25s cubic-bezier(.4, 0, .2, 1),
        box-shadow .25s cubic-bezier(.4, 0, .2, 1),
        border-color .25s cubic-bezier(.4, 0, .2, 1),
        background .25s cubic-bezier(.4, 0, .2, 1);
    }

    #view-find-tournaments .ti-card:hover,
    #view-resources .ti-card:hover {
      background: linear-gradient(145deg, #264168, #2E4A72);
      border-color: color-mix(in oklab, var(--accent) 50%, transparent);
      border-left-color: var(--ks-accent);
      box-shadow:
        inset 0 1px 0 rgba(255, 255, 255, .08),
        0 14px 36px rgba(0, 0, 0, .35),
        0 0 16px color-mix(in oklab, var(--accent) 6%, transparent);
      transform: translateY(-2px);
    }

    #view-find-tournaments .ti-card:focus-visible,
    #view-resources .ti-card:focus-visible {
      outline: 2px solid var(--ks-accent);
      outline-offset: 2px;
    }

    #view-find-tournaments .ti-card-title,
    #view-resources .ti-card-title {
      color: #FFFFFF;
      font-size: 1.1rem;
      font-weight: 800;
      letter-spacing: .2px;
    }

    #view-find-tournaments .ti-card-desc,
    #view-resources .ti-card-desc {
      color: #CBD5E1;
      font-size: .9rem;
      font-weight: 600;
      line-height: 1.5;
    }

    #view-find-tournaments .ti-card-icon,
    #view-resources .ti-card-icon {
      background: color-mix(in oklab, var(--accent) 12%, transparent);
      border-radius: 12px;
    }

    #view-find-tournaments .ti-card-arrow,
    #view-resources .ti-card-arrow {
      background: linear-gradient(135deg, var(--ks-accent), var(--accent-deep));
      color: var(--ks-on-accent);
      border-radius: 10px;
      box-shadow: 0 2px 8px color-mix(in oklab, var(--accent) 25%, transparent);
    }

    /* AAU's own colour — see the note in dojo-tournament-info-shell. */
    #view-find-tournaments .ti-card.ti-border-gold,
    #view-resources .ti-card.ti-border-gold {
      border-left-color: #F4D03F;
    }

    #view-find-tournaments .ti-card.ti-border-blue,
    #view-resources .ti-card.ti-border-blue {
      border-left-color: #5DADE2;
    }

    #view-find-tournaments .ti-card.ti-border-green,
    #view-resources .ti-card.ti-border-green {
      border-left-color: #27AE60;
    }

    #view-find-tournaments .ti-card.ti-border-purple,
    #view-resources .ti-card.ti-border-purple {
      border-left-color: #9B59B6;
    }

    /* The AAU chip, keeping AAU's colour like its blue and green siblings. */
    #view-find-tournaments .ti-bg-gold,
    #view-resources .ti-bg-gold {
      background: rgba(244, 208, 63, .14);
      color: #F4D03F;
    }

    /* The category chips are NOT overridden here any more.
     *
     * These were the dark-card values — a light glyph on a barely-tinted well,
     * which is right when the card behind it is navy. This file wins on a card
     * that is #FFF, so they landed on white: blue at 2.13:1 and green at
     * 2.50:1 against a 3:1 bar for a graphical object.
     *
     * Lightening the wells cannot fix that, which is worth writing down. For
     * #5DADE2 to clear 3:1 the background needs a relative luminance above
     * 1.23, and white is 1.0 — the mark is simply too light to be seen against
     * anything lighter than itself. The only honest options were to darken the
     * glyph or to darken the well.
     *
     * Neither was needed: dojo-tournament-info-shell.v1.css already carries the
     * light-surface values, #2874A6 / #1E8449 / #76448A on a 15% tint, and they
     * measure 4.34:1, 4.06:1 and 5.85:1. Removing the override lets the correct
     * rule through. The category hues are unchanged, and no third-party mark is
     * touched — AAU's and NKF's are <img> logos that CSS never coloured. */

    /* ── One exception, and only in dark ──────────────────────────────────────
     * Those light-surface values are right on a white card. In dark mode the
     * card composites to #04080F and the family splits: blue holds 3.95:1 and
     * green 4.25:1, but purple is the darkest of the three and falls to 2.83:1,
     * under the 3:1 a graphical object needs. Gold was lifted for this surface
     * long ago; purple never was, and that is the whole of the inconsistency.
     *
     * #9B59B6 is not a new colour — it is the hue the chip's own 15% well is
     * already mixed from, so the family keeps its palette while landing at
     * 4.30:1, beside its blue and green siblings. Scoped to dark only: on white
     * the darker #76448A is the better mark, at 5.85:1. */
    :root[data-theme="dark"] #view-find-tournaments .ti-bg-purple,
    :root[data-theme="dark"] #view-resources .ti-bg-purple {
      color: #9B59B6;
    }

    @media (prefers-color-scheme: dark) {
      :root:not([data-theme]) #view-find-tournaments .ti-bg-purple,
      :root:not([data-theme]) #view-resources .ti-bg-purple {
        color: #9B59B6;
      }
    }


/* ══════════════════════════════════════════════════════════════════════
   dojo-schedule-calendar-shell-dark.v1.css
   ══════════════════════════════════════════════════════════════════════ */
    /* This was part of the dark treatment for #view-schedule and set its colours
       with !important, so the view could not be restyled without fighting it.
       dojo-schedule-shell.v1.css owns them through the semantic tokens now, which
       is what lets this view answer for both themes.

       Its structural siblings are untouched: -responsive-dark carries padding and
       radius rather than colour, and -focus-visible-dark and -reduced-motion-dark
       set no !important, so ordinary cascade order is enough for those.

       Kept as a file rather than deleted: 166 link tags reference these by name
       and a 404 per visitor is the worse trade. */


/* ══════════════════════════════════════════════════════════════════════
   dojo-schedule-focus-visible-dark.v1.css
   ══════════════════════════════════════════════════════════════════════ */
    #view-schedule .home-calendar-mini-cell:focus-visible,
    #view-schedule .sch-action-link:focus-visible,
    #view-schedule .sch-quick-link:focus-visible,
    #view-schedule .sch-clear-btn:focus-visible,
    #view-schedule .btn:focus-visible {
      outline: 2px solid var(--ks-accent);
      outline-offset: 2px;
      box-shadow: 0 0 0 4px color-mix(in oklab, var(--accent) 15%, transparent);
    }


/* ══════════════════════════════════════════════════════════════════════
   dojo-schedule-responsive-dark.v1.css
   ══════════════════════════════════════════════════════════════════════ */
    @media (max-width: 767px) {
      #view-schedule .home-calendar {
        border-radius: 14px !important;
        padding: 1rem !important;
      }

      #view-schedule .home-calendar-item {
        padding: .9rem !important;
      }

      #view-schedule .home-calendar-item:hover,
      #view-schedule .sch-quick-link:hover,
      #view-schedule .sch-action-link:hover {
        transform: none;
      }

      #view-schedule .home-calendar-list {
        gap: .85rem !important;
      }
    }


/* ══════════════════════════════════════════════════════════════════════
   dojo-schedule-reduced-motion-dark.v1.css
   ══════════════════════════════════════════════════════════════════════ */
    @media (prefers-reduced-motion: reduce) {

      #view-schedule .home-calendar,
      #view-schedule .home-calendar-item,
      #view-schedule .home-calendar-mini-cell,
      #view-schedule .sch-action-link,
      #view-schedule .sch-quick-link {
        transition: none !important;
      }
    }


/* ══════════════════════════════════════════════════════════════════════
   dojo-homann-tenant-lifecycle-shell.v1.css
   ══════════════════════════════════════════════════════════════════════ */
.ks-tenant-lifecycle-shell {
  position: fixed;
  inset: 0;
  z-index: calc(var(--z-modal) + 20);
  display: grid;
  place-items: center;
  min-height: 100vh;
  padding: max(24px, env(safe-area-inset-top)) 20px max(24px, env(safe-area-inset-bottom));
  overflow-x: hidden;
  overflow-y: auto;
  background: #050a14;
  color: var(--text);
}

.ks-tenant-lifecycle-shell[hidden] {
  display: none;
}

/* ── THE ONE OVERLAY THE SHELL MUST NOT COVER ──────────────────────────────
   The shell hides every tenant surface behind it and deliberately spares the
   sign-in dialog — setTenantSurfacesAvailable() excludes #m-login by name, so
   it is never made inert and never forced shut. That exclusion was pointless in
   practice: .overlay sits at --z-overlay (300) and this shell at --z-modal + 20
   (420), so the dialog opened UNDERNEATH an opaque full-screen panel.

   What that produced is the whole of "the Sign In control doesn't work". Both
   states that offer a sign-in button are states where the shell is up: a gated
   dojo's access-code card, whose copy tells members to sign in rather than use
   the code, and a draft tenant's "Sign in to preview". Pressing either opened
   a dialog nobody could see, over a page that then appeared to have ignored the
   click. Caught by Playwright reporting the shell as intercepting pointer
   events on a button it called visible.

   Above the shell, below --z-toast (500), so a refusal still lands on top of
   the dialog that caused it. */
#m-login,
/* Email verification belongs beside sign-in for the same reason. It is an
   ACCOUNT dialog, not a tenant surface: its three controls are refresh, resend
   and sign out, none of which depend on the dojo being available. Hiding it
   behind the shell meant a reader whose verification refresh failed had the
   explanation taken off the screen by the very state the failure produced —
   they were returned to the code box with no idea why. */
#m-email-verification {
  z-index: calc(var(--z-modal) + 30);
}

.ks-tenant-lifecycle-card {
  width: min(100%, 560px);
  padding: 40px;
  border: 1px solid rgba(240, 220, 154, 0.28);
  border-radius: var(--radius-md);
  background: #0a1324;
  box-shadow: var(--shadow-xl);
  text-align: center;
}

/* The crest carries its own navy ring, so the drawn circle that used to frame
   the "KS" letters is removed rather than kept around it: two concentric rings
   in slightly different navies is the sort of detail that reads as a mistake. */
.ks-tenant-lifecycle-mark {
  display: block;
  width: 88px;
  height: 88px;
  margin: 0 auto 22px;
  object-fit: contain;
}

.ks-tenant-lifecycle-eyebrow {
  margin-bottom: 10px;
  color: var(--ks-accent-strong);
  font-size: var(--text-sm);
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0;
}

.ks-tenant-lifecycle-title {
  margin: 0;
  color: var(--white);
  font-family: var(--ks-display);
  font-size: var(--text-2xl);
  line-height: var(--leading-2xl);
  letter-spacing: 0;
  overflow-wrap: anywhere;
}

.ks-tenant-lifecycle-copy {
  max-width: 46ch;
  margin: 16px auto 0;
  color: var(--muted);
  font-size: var(--text-md);
  line-height: 1.65;
  overflow-wrap: anywhere;
}

/* ── Team access code ──────────────────────────────────────────────────────
   Literal colours, not tokens, for the same reason the rest of this file uses
   them: the shell is unconditionally dark whatever theme the reader is in, so a
   themed token would be resolved against the wrong surface. Each value below is
   measured against the card's #0A1324 rather than assumed —
   #FF8A80 reaches 8.2:1 and #FFFFFF 17.4:1. */
.ks-team-access-form {
  margin-top: 24px;
  text-align: left;
}

.ks-team-access-form[hidden] {
  display: none;
}

.ks-team-access-label {
  display: block;
  margin-bottom: 8px;
  color: var(--white);
  font-size: var(--text-sm);
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.04em;
}

.ks-team-access-row {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto;
  gap: 10px;
}

.ks-team-access-input {
  min-width: 0;
  min-height: 48px;
  padding: 12px 14px;
  border: 1px solid rgba(255, 255, 255, 0.22);
  border-radius: var(--radius-sm);
  background: #0D1A30;
  color: #FFFFFF;
  font: inherit;
  font-size: var(--text-base);
  /* A code is read aloud and written on a whiteboard, so it is stored and
     compared case-insensitively by the server. Showing it upper-case here means
     what the visitor sees is what the dojo wrote down. */
  text-transform: uppercase;
  letter-spacing: 0.08em;
}

.ks-team-access-submit {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-height: 48px;
  padding: 12px 22px;
  border: 1px solid transparent;
  border-radius: var(--radius-sm);
  background: var(--ks-accent);
  /* --ks-on-accent, not a literal. It resolves to --accent-ink, which the
     platform derives from the accent's own luminance precisely so a filled
     accent button is readable whatever colour a dojo picks. The literal
     #07101F that stood here reaches 3.20:1 on the default accent — below AA
     for a bold 0.875rem label — and would have been wrong in a different
     direction for every dojo that sets its own. Measured, not assumed: the
     `the gate clears WCAG contrast` case in tests/security/team-access-entry
     runs the shared rendered-contrast audit over this card as it renders. */
  color: var(--ks-on-accent);
  font: inherit;
  font-size: var(--text-base);
  font-weight: 700;
  cursor: pointer;
}

.ks-team-access-submit:disabled,
.ks-team-access-input:disabled {
  opacity: 0.6;
  cursor: default;
}

.ks-team-access-status {
  margin-top: 10px;
  color: #FF8A80;
  font-size: var(--text-base);
  line-height: 1.5;
  overflow-wrap: anywhere;
}

.ks-team-access-status[hidden] {
  display: none;
}

.ks-team-access-input:focus-visible,
.ks-team-access-submit:focus-visible {
  outline: 2px solid var(--ks-accent);
  outline-offset: 3px;
  box-shadow: 0 0 0 5px color-mix(in oklab, var(--accent) 20%, transparent);
}

.ks-tenant-lifecycle-actions {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 12px;
  min-height: 44px;
  margin-top: 28px;
}

.ks-tenant-lifecycle-action {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: 0;
  min-height: 44px;
  padding: 11px 18px;
  border: 1px solid transparent;
  border-radius: var(--radius-sm);
  font: inherit;
  font-size: var(--text-base);
  font-weight: 700;
  line-height: 1.3;
  text-align: center;
  text-decoration: none;
  overflow-wrap: anywhere;
  cursor: pointer;
}

.ks-tenant-lifecycle-action[hidden] {
  display: none;
}

.ks-tenant-lifecycle-action-primary {
  background: var(--ks-accent);
  /* Same correction as .ks-team-access-submit above, and it has to be the same:
     the two buttons sit side by side on the gate, so one readable and one at
     3.20:1 would look like a mistake even to somebody not measuring. */
  color: var(--ks-on-accent);
}

.ks-tenant-lifecycle-action-secondary {
  border-color: rgba(255, 255, 255, 0.22);
  background: transparent;
  color: var(--white);
}

.ks-tenant-lifecycle-support {
  display: inline-flex;
  align-items: center;
  min-height: 44px;
  margin-top: 12px;
  color: var(--ks-accent-strong);
  font-size: var(--text-base);
}

.ks-tenant-lifecycle-support[hidden] {
  display: none;
}

.ks-tenant-lifecycle-action:focus-visible,
.ks-tenant-lifecycle-support:focus-visible {
  outline: 2px solid var(--ks-accent);
  outline-offset: 3px;
  box-shadow: 0 0 0 5px color-mix(in oklab, var(--accent) 20%, transparent);
}

.ks-tenant-draft-preview-banner {
  position: fixed;
  inset: 72px 0 auto;
  z-index: var(--z-sticky);
  padding: 10px 20px;
  border-bottom: 1px solid color-mix(in oklab, var(--accent) 38%, transparent);
  background: #14213a;
  color: var(--ks-accent-strong);
  font-size: var(--text-base);
  font-weight: 700;
  text-align: center;
}

.ks-tenant-draft-preview-banner[hidden] {
  display: none;
}

body[data-tenant-availability]:not([data-tenant-availability="active"]):not([data-tenant-availability="draft_preview"]) .ks-tenant-runtime-hidden {
  visibility: hidden !important;
  pointer-events: none !important;
}

body[data-tenant-availability]:not([data-tenant-availability="active"]):not([data-tenant-availability="draft_preview"]) .overlay:not(#m-login):not(#m-email-verification),
body[data-tenant-availability]:not([data-tenant-availability="active"]):not([data-tenant-availability="draft_preview"]) nav,
body[data-tenant-availability]:not([data-tenant-availability="active"]):not([data-tenant-availability="draft_preview"]) .mobile-dock,
body[data-tenant-availability]:not([data-tenant-availability="active"]):not([data-tenant-availability="draft_preview"]) .view,
body[data-tenant-availability]:not([data-tenant-availability="active"]):not([data-tenant-availability="draft_preview"]) footer {
  visibility: hidden !important;
  pointer-events: none !important;
}

body[data-tenant-availability="active"] .ks-tenant-runtime-hidden,
body[data-tenant-availability="draft_preview"] .ks-tenant-runtime-hidden {
  visibility: visible;
  pointer-events: auto;
}

@media (max-width: 520px) {
  .ks-tenant-lifecycle-shell {
    padding-inline: 16px;
  }

  .ks-tenant-lifecycle-card {
    padding: 32px 20px;
  }

  .ks-tenant-lifecycle-title {
    font-size: var(--text-xl);
  }

  .ks-tenant-lifecycle-actions {
    grid-template-columns: minmax(0, 1fr);
  }

  /* The code and its button stack rather than squeeze. A 64-character field
     beside a button on a 320px screen leaves neither usable. */
  .ks-team-access-row {
    grid-template-columns: minmax(0, 1fr);
  }
}

@media (prefers-reduced-motion: reduce) {
  .ks-tenant-lifecycle-shell,
  .ks-tenant-lifecycle-card,
  .ks-tenant-lifecycle-action,
  .ks-tenant-draft-preview-banner {
    scroll-behavior: auto;
    transition: none !important;
    animation: none !important;
  }
}


/* ══════════════════════════════════════════════════════════════════════
   dojo-admin-dashboard-shell.v1.css
   ══════════════════════════════════════════════════════════════════════ */
    /* ══════════════════════════════════════════════════════════════════════════
       ADMIN DASHBOARD SHELL — premium layout pass over the existing admin view.

       Loaded AFTER dojo-admin-light-theme-override.v1.css so it wins on cascade
       order without editing 1,985 lines of working CSS. Every selector is scoped
       to #view-admin; nothing here can reach another view.

       Layout is applied with CSS Grid directly on #view-admin, so the existing
       markup order (topbar, welcome, stats, tabs, tab panels) needs no wrapper
       element and no JavaScript change. The tab strip IS the sidebar at desktop
       widths — same elements, same onclick handlers, different presentation —
       which is why switchAdminTab() keeps working untouched.
       ══════════════════════════════════════════════════════════════════════════ */

    /* ── Design tokens, scoped to the dashboard ──────────────────────────────── */
    /* An alias layer, not a second palette.
       These were literals — a parallel copy of the theme layer that drifted
       from it. --adm-ink-3 was #98A2B3, which is the exact value the theme
       tokens name and reject: "the admin shell's #98A2B3 manages only 2.58:1
       and is not carried over". It was carried over here, and the dashboard
       shipped labels at 2.58:1 on white. The names are kept so no rule in this
       file has to change; what they resolve to is now the shared system. */
    #view-admin {
      --adm-canvas: var(--ks-canvas);
      --adm-surface: var(--ks-surface);
      --adm-line: var(--ks-line);
      --adm-line-soft: var(--ks-line-soft);
      --adm-ink: var(--ks-ink);
      --adm-ink-2: var(--ks-ink-2);
      --adm-ink-3: var(--ks-ink-3);
      --adm-rail: var(--ks-band);
      --adm-rail-2: var(--ks-band-raised);
      --adm-rail-line: var(--ks-band-line);
      --adm-rail-ink: var(--ks-band-ink-2);
      --adm-accent: var(--ks-accent);
      /* The accent AS TEXT on the dark rail. --adm-accent is the fill and is
         2.85:1 there; the rail needs the lightness-floored form. */
      --adm-rail-accent: var(--ks-band-accent);
      --adm-accent-soft: color-mix(in oklab, var(--accent) 12%, transparent);
      --adm-radius: 14px;
      --adm-radius-sm: 10px;
      --adm-rail-w: 250px;
      --adm-gutter: 1.75rem;
      /* Height of the fixed site nav; .view.active reserves the same 72px. */
      --adm-nav-h: 72px;
      --adm-shadow-1: 0 1px 2px rgba(16, 24, 40, .04), 0 1px 3px rgba(16, 24, 40, .06);
      --adm-shadow-2: 0 4px 8px -2px rgba(16, 24, 40, .08), 0 2px 4px -2px rgba(16, 24, 40, .04);
      --adm-shadow-3: 0 12px 24px -6px rgba(16, 24, 40, .12), 0 4px 8px -4px rgba(16, 24, 40, .06);
      background: var(--adm-canvas);
      color: var(--adm-ink);
    }

    /* ══ DESKTOP: two-column shell with a navy rail ═════════════════════════════
       Explicit row/column placement rather than auto-flow: exactly one
       .admin-tab-content carries .active at a time and the rest are display:none,
       so every visible panel can safely claim the same cell.
       ═════════════════════════════════════════════════════════════════════════ */
    @media (min-width: 1101px) {
      #view-admin.active {
        display: grid;
        grid-template-columns: var(--adm-rail-w) minmax(0, 1fr);
        /* Two rows since the greeting and stat cards moved INTO the Overview
           panel (they used to be rows of their own, repeated above every
           section): the topbar, then rail-beside-panel. */
        grid-template-rows: auto minmax(0, 1fr);
        align-items: start;
      }

      #view-admin>.admin-topbar {
        grid-column: 1 / -1;
        grid-row: 1;
        /* Static on desktop: the rail below is the element worth pinning, and
           stacking two sticky bars under the fixed site nav would require a
           hardcoded topbar height that drifts the moment its contents change. */
        position: static;
      }

      #view-admin>.admin-tab-content.active {
        grid-column: 2;
        grid-row: 2;
        min-width: 0;
      }

      /* ── The rail ──────────────────────────────────────────────────────────── */
      #view-admin>.admin-tabs {
        grid-column: 1;
        grid-row: 2;
        align-self: stretch;
        display: flex;
        flex-direction: column;
        gap: 2px;
        padding: 1.25rem .75rem 2rem;
        background: var(--adm-rail);
        border-bottom: none;
        border-right: 1px solid var(--adm-rail-line);
        position: sticky;
        top: var(--adm-nav-h);
        max-height: calc(100vh - var(--adm-nav-h));
        overflow-y: auto;
        overscroll-behavior: contain;
      }

      #view-admin .admin-tab {
        display: flex;
        align-items: center;
        gap: .7rem;
        width: 100%;
        text-align: left;
        padding: 11px 14px;
        margin-bottom: 0;
        border: none;
        border-radius: var(--adm-radius-sm);
        background: transparent;
        color: var(--adm-rail-ink);
        font-family: 'Raleway', sans-serif;
        font-size: .74rem;
        font-weight: 600;
        letter-spacing: .06em;
        text-transform: none;
        position: relative;
      }

      #view-admin .admin-tab::before {
        content: '';
        position: absolute;
        left: 0;
        top: 50%;
        width: 3px;
        height: 0;
        border-radius: 0 3px 3px 0;
        background: var(--adm-accent);
        transform: translateY(-50%);
        transition: height .18s ease;
      }

      #view-admin .admin-tab:hover {
        background: rgba(255, 255, 255, .05);
        color: #fff;
      }

      #view-admin .admin-tab.active {
        background: var(--adm-rail-2);
        color: #fff;
      }

      #view-admin .admin-tab.active::before {
        height: 60%;
      }

      /* The icon follows the active tab's own white. It was --adm-accent here,
         which never rendered while the icons were emoji (they carry their own
         colours) — the sprite icons exposed it, and accent-on-rail measured
         2.61:1 in the rendered audit. The accent bar ::before still marks the
         active tab. */
      #view-admin .admin-tab.active .admin-tab-ico {
        color: inherit;
      }

      #view-admin .admin-tab:focus-visible {
        outline-offset: -2px;
      }

      /* Rail section heading — meaningless in the horizontal strip, so it is
         revealed only where the rail exists. */
      #view-admin .admin-tabs-heading {
        display: block;
        padding: 0 14px .6rem;
        font-size: .55rem;
        font-weight: 700;
        letter-spacing: .22em;
        text-transform: uppercase;
        color: rgba(255, 255, 255, .34);
      }
    }

    #view-admin .admin-tabs-heading {
      display: none;
    }

    /* ── Tab internals, shared by rail and strip ──────────────────────────────── */
    #view-admin .admin-tab-ico {
      flex: 0 0 auto;
      width: 18px;
      text-align: center;
      font-size: .9rem;
      line-height: 1;
      color: inherit;
    }

    #view-admin .admin-tab-txt {
      min-width: 0;
    }

    /* ══ TABLET / PHONE: horizontal strip, scrollable, never wrapping ══════════ */
    @media (max-width: 1100px) {
      #view-admin>.admin-tabs {
        display: flex;
        flex-direction: row;
        flex-wrap: nowrap;
        gap: .25rem;
        overflow-x: auto;
        overscroll-behavior-x: contain;
        scrollbar-width: none;
        -webkit-overflow-scrolling: touch;
        padding: 0 var(--adm-gutter);
        background: var(--adm-surface);
        border-bottom: 1px solid var(--adm-line);
      }

      #view-admin>.admin-tabs::-webkit-scrollbar {
        display: none;
      }

      /* THE STRIP HAS TO LOOK SCROLLABLE. Measured 2026-08-22 on a 412px
         phone: the section switcher is 1,234px of content in a 412px box, so
         six of its nine sections -- Calendar, Announcements, Tournaments, Site
         Images, Team Preview and Settings -- were off the right edge, behind a
         scrollbar this file hides two rules up. Nothing on screen said they
         existed.

         Scrolling shadows rather than a fixed fade: the two cover gradients are
         attached to the CONTENT and the two shadows to the VIEWPORT, so each
         shadow is hidden by its cover exactly when that end is reached. The
         affordance is therefore position-aware with no script and no listener
         -- it appears when there is more to see and goes when there is not. */
      #view-admin>.admin-tabs {
        background-image:
          linear-gradient(to right, var(--adm-surface), rgba(255, 255, 255, 0)),
          linear-gradient(to left, var(--adm-surface), rgba(255, 255, 255, 0)),
          radial-gradient(farthest-side at 0 50%, rgba(16, 24, 40, .16), rgba(16, 24, 40, 0)),
          radial-gradient(farthest-side at 100% 50%, rgba(16, 24, 40, .16), rgba(16, 24, 40, 0));
        background-position: left center, right center, left center, right center;
        background-repeat: no-repeat;
        background-size: 28px 100%, 28px 100%, 12px 100%, 12px 100%;
        background-attachment: local, local, scroll, scroll;
      }

      #view-admin .admin-tab {
        flex: 0 0 auto;
        display: inline-flex;
        align-items: center;
        gap: .45rem;
        white-space: nowrap;
        padding: 13px 14px;
        border: none;
        border-bottom: 2px solid transparent;
        margin-bottom: -1px;
        border-radius: 0;
        background: transparent;
        color: var(--adm-ink-3);
        font-family: 'Raleway', sans-serif;
        font-size: .7rem;
        font-weight: 700;
        letter-spacing: .08em;
      }

      #view-admin .admin-tab.active {
        color: var(--adm-ink);
        border-bottom-color: var(--adm-accent);
      }
    }

    /* ══ TOPBAR ════════════════════════════════════════════════════════════════ */
    #view-admin .admin-topbar {
      padding: .85rem var(--adm-gutter);
      background: var(--adm-rail);
      border-bottom: 1px solid var(--adm-rail-line);
      box-shadow: none;
    }

    #view-admin .admin-topbar-brand img {
      width: 36px;
      height: 36px;
    }

    #view-admin .admin-topbar-brand-title {
      font-size: .78rem;
      letter-spacing: .14em;
    }

    #view-admin .admin-topbar-brand-sub {
      font-size: .52rem;
      letter-spacing: .18em;
      color: var(--adm-rail-accent);
    }

    #view-admin .admin-topbar-search input {
      padding: 9px 14px 9px 34px;
      border-radius: var(--adm-radius-sm);
      background: rgba(255, 255, 255, .06);
      border: 1px solid rgba(255, 255, 255, .1);
      font-size: .78rem;
    }

    #view-admin .admin-topbar-search input:focus {
      background: rgba(255, 255, 255, .1);
      border-color: color-mix(in oklab, var(--accent) 55%, transparent);
      box-shadow: 0 0 0 3px color-mix(in oklab, var(--accent) 14%, transparent);
    }

    /* ══ PAGE HEADER ═══════════════════════════════════════════════════════════ */
    #view-admin .admin-welcome {
      padding: 1.6rem var(--adm-gutter) 1.35rem;
      background: transparent;
      border-bottom: none;
    }

    #view-admin .admin-welcome h2 {
      font-size: 1.45rem;
      letter-spacing: .02em;
      color: var(--adm-ink);
    }

    #view-admin .admin-welcome p {
      font-size: .82rem;
      color: var(--adm-ink-2);
      letter-spacing: 0;
    }

    /* ══ STAT CARDS ════════════════════════════════════════════════════════════ */
    #view-admin .admin-stats {
      padding: 0 var(--adm-gutter) 1.25rem;
      background: transparent;
      gap: 1rem;
    }

    /* Grid rather than flex: the markup is three flat siblings (icon, label,
       value) with no wrapper, so the icon claims column 1 across both rows and
       the text stacks beside it without touching the HTML. */
    #view-admin .admin-stat-card {
      display: grid;
      grid-template-columns: auto minmax(0, 1fr);
      grid-template-rows: auto auto;
      align-items: center;
      column-gap: .95rem;
      padding: 1.15rem 1.25rem;
      background: var(--adm-surface);
      border: 1px solid var(--adm-line);
      border-radius: var(--adm-radius);
      box-shadow: var(--adm-shadow-1);
      transition: box-shadow .2s ease, border-color .2s ease;
    }

    #view-admin .admin-stat-card:hover {
      transform: none;
      border-color: color-mix(in oklab, var(--accent) 45%, transparent);
      box-shadow: var(--adm-shadow-2);
    }

    #view-admin .admin-stat-icon {
      grid-column: 1;
      grid-row: 1 / span 2;
      width: 44px;
      height: 44px;
      margin-bottom: 0;
      border-radius: 12px;
      background: var(--adm-accent-soft);
      font-size: 1.15rem;
    }

    #view-admin .admin-stat-label {
      grid-column: 2;
      grid-row: 1;
      align-self: end;
      font-size: .55rem;
      letter-spacing: .18em;
      color: var(--adm-ink-3);
      margin-bottom: .2rem;
    }

    #view-admin .admin-stat-val {
      grid-column: 2;
      grid-row: 2;
      align-self: start;
      font-size: 1.7rem;
      color: var(--adm-ink);
    }

    /* ══ SECTIONS / CARDS ══════════════════════════════════════════════════════ */
    #view-admin .admin-section {
      background: var(--adm-surface);
      border: 1px solid var(--adm-line);
      border-radius: var(--adm-radius);
      box-shadow: var(--adm-shadow-1);
      margin: 0 var(--adm-gutter) 1.25rem;
      padding: 1.5rem;
      box-sizing: border-box;
    }

    #view-admin .admin-tab-content.active {
      padding-bottom: 1.5rem;
    }

    /* ══ CASCADE RECONCILIATION ════════════════════════════════════════════════
       The older stylesheet pins these with !important, so specificity alone
       cannot reach them. It also gives the Overview cards five different accent
       colours (navy, gold, indigo, emerald, rose) — the single loudest reason
       the dashboard reads as generic. One restrained surface treatment replaces
       all five; colour is reserved for state (badges) and for the active rail
       item. These are the only !important declarations in this file.
       ═════════════════════════════════════════════════════════════════════════ */
    #view-admin .admin-section,
    #view-admin .dash-uploads-col.admin-section,
    #view-admin .dash-users-col.admin-section,
    #view-admin .admin-section.dash-cal-section,
    #view-admin .dash-cal-edit-panel,
    #view-admin #dash-upcoming-sidebar {
      background: var(--adm-surface) !important;
      border: 1px solid var(--adm-line) !important;
      border-radius: var(--adm-radius) !important;
      box-shadow: var(--adm-shadow-1) !important;
    }

    #view-admin .admin-section-title {
      color: var(--adm-ink);
      font-size: .82rem !important;
      letter-spacing: .1em !important;
    }

    /* ══ ANNOUNCEMENTS TAB ═════════════════════════════════════════════════════
       Announcement and Spotlight are two editors for the same surface, so they
       share one page under a sub-tab rather than two rail entries. The panel is
       the same .cal-edit-panel card the event editor uses, but that card was
       sized for a sidebar column; left unconstrained on a full-width page it
       would stretch a short form across 1100px of empty space.
       ═════════════════════════════════════════════════════════════════════════ */
    #view-admin .adm-ann-panel {
      background: var(--adm-surface) !important;
      border: 1px solid var(--adm-line) !important;
      border-radius: var(--adm-radius) !important;
      box-shadow: var(--adm-shadow-1) !important;
      max-width: 720px;
    }

    /* .cal-edit-tab was written for divs and sets no background or border, so
       promoting the sub-tabs to real buttons for keyboard access would otherwise
       drop browser-default chrome straight into the card.

       THE BACKGROUND RESET IS SCOPED TO THE INACTIVE TAB, and that is the whole
       point of this edit. `#view-admin .cal-edit-tab` is (1,1,0); the selected
       state, `.cal-edit-tab.active`, is (0,2,0). An id beats any number of
       classes, so inside the admin view this reset silently erased the selected
       tab's fill — measured 2026-08-22, the Announcement/Spotlight switcher
       reported background-color rgba(0, 0, 0, 0) on the ACTIVE tab, leaving a
       three-shade text difference as the only signal of which editor was open.
       Two editors that write two different documents, told apart by a grey. */
    #view-admin .cal-edit-tab {
      appearance: none;
      border: 0;
      margin: 0;
      font-family: inherit;
    }

    #view-admin .cal-edit-tab:not(.active) {
      background: none;
    }

    /* The selected editor, said plainly: a raised surface inside the track, a
       hairline to lift it off the groove, and the accent underline the rail
       tabs use so the two switchers speak the same language. */
    #view-admin .cal-edit-tab.active {
      background: var(--adm-surface, #fff);
      color: var(--adm-ink, #101828);
      box-shadow: 0 1px 2px rgba(16, 24, 40, .1), 0 0 0 1px rgba(16, 24, 40, .06);
      font-weight: 800;
    }

    #view-admin .cal-edit-tab.active::after {
      content: '';
      position: absolute;
      left: 38%;
      right: 38%;
      bottom: 5px;
      height: 2px;
      border-radius: 2px;
      background: var(--adm-accent);
    }

    /* The tab is the positioning context for that underline. `.cal-edit-tab`
       already sets position: relative in the light theme; naming it here means
       the marker cannot escape to the page if that ever changes. */
    #view-admin .cal-edit-tab {
      position: relative;
    }

    #view-admin .cal-edit-tab .ks-icon {
      /* The icon rode the baseline and pulled the label up by a pixel. */
      vertical-align: -2px;
    }

    /* ══ TABLES ════════════════════════════════════════════════════════════════
       Sticky header, no zebra striping. Alternating fills fight with the status,
       belt and role badges the roster relies on; a single hover fill reads
       cleaner and keeps every badge legible on every row.
       ═════════════════════════════════════════════════════════════════════════ */
    #view-admin .admin-table {
      border-collapse: separate;
      border-spacing: 0;
    }

    /* dojo-admin-light-theme-override.v1.css names #admin-users-table and
       #admin-tournaments-table here but omits the pending-approvals container,
       so its 580px table was clipped inside a 332px card on a phone with no way
       to reach the Requested/Actions columns. Same treatment, same convention. */
    #view-admin #admin-pending-approvals {
      overflow-x: auto;
      -webkit-overflow-scrolling: touch;
      width: 100%;
    }

    #view-admin .admin-table th {
      position: sticky;
      top: 0;
      z-index: 2;
      background: #FAFBFC;
      color: var(--adm-ink-2);
      font-weight: 700;
      text-transform: uppercase;
      border-bottom: 1px solid var(--adm-line);
      padding: 11px 14px;
      /* Reaches past the older stylesheet's !important header typography. */
      font-size: .6rem !important;
      letter-spacing: .12em !important;
    }

    #view-admin .admin-table td {
      border-bottom: 1px solid var(--adm-line-soft);
      padding: 13px 14px;
      color: var(--adm-ink);
      vertical-align: middle;
    }

    #view-admin .admin-table tbody tr td,
    #view-admin .admin-table tbody tr:nth-child(even) td {
      background: var(--adm-surface);
    }

    #view-admin .admin-table tbody tr:hover td,
    #view-admin .admin-table tbody tr:nth-child(even):hover td {
      background: #F7F8FB;
    }

    #view-admin .admin-table tbody tr:last-child td {
      border-bottom: none;
    }

    /* ══ BADGES ════════════════════════════════════════════════════════════════ */
    #view-admin .role-badge,
    #view-admin .status-badge,
    #view-admin .belt-badge {
      border-radius: 999px;
      font-size: .58rem;
      font-weight: 700;
      letter-spacing: .08em;
      padding: 3px 10px;
      line-height: 1.6;
      white-space: nowrap;
    }

    /* ══ FORMS ═════════════════════════════════════════════════════════════════ */
    #view-admin .fi-inp,
    #view-admin .admin-filter-bar input[type="text"],
    #view-admin .admin-filter-bar select,
    #view-admin .dash-user-filter-row input[type="text"],
    #view-admin .dash-user-filter-row select,
    #view-admin .ta-field input,
    #view-admin .ta-field select,
    #view-admin .ta-field textarea {
      border-radius: var(--adm-radius-sm);
      border: 1px solid var(--adm-line);
      background: var(--adm-surface);
      color: var(--adm-ink);
      transition: border-color .16s ease, box-shadow .16s ease;
    }

    #view-admin .fi-inp:focus,
    #view-admin .admin-filter-bar input[type="text"]:focus,
    #view-admin .admin-filter-bar select:focus,
    #view-admin .dash-user-filter-row input[type="text"]:focus,
    #view-admin .dash-user-filter-row select:focus,
    #view-admin .ta-field input:focus,
    #view-admin .ta-field select:focus,
    #view-admin .ta-field textarea:focus {
      outline: none;
      border-color: var(--adm-accent);
      box-shadow: 0 0 0 3px color-mix(in oklab, var(--accent) 16%, transparent);
    }

    #view-admin .fl,
    #view-admin .ta-field label {
      color: var(--adm-ink-2);
      font-weight: 700;
      letter-spacing: .06em;
    }

    /* ══ MENUS ═════════════════════════════════════════════════════════════════ */
    #view-admin .adm-dropdown {
      border-radius: var(--adm-radius-sm);
      border: 1px solid var(--adm-line);
      box-shadow: var(--adm-shadow-3);
      overflow: hidden;
    }

    #view-admin .adm-three-dot {
      border-radius: 8px;
    }

    /* ══ DISABLED CONTROLS ═════════════════════════════════════════════════════
       The Settings save button stays disabled until a load has populated the
       form. Without a visible disabled treatment that guard reads as a dead
       button rather than a deliberate one.
       ═════════════════════════════════════════════════════════════════════════ */
    #view-admin button:disabled,
    #view-admin .btn:disabled {
      opacity: .45;
      cursor: not-allowed;
      box-shadow: none;
    }

    /* ══ KEYBOARD FOCUS ════════════════════════════════════════════════════════ */
    #view-admin .admin-tab:focus-visible,
    #view-admin .btn:focus-visible,
    #view-admin button:focus-visible,
    #view-admin a:focus-visible,
    #view-admin input:focus-visible,
    #view-admin select:focus-visible,
    #view-admin textarea:focus-visible {
      outline: 2px solid var(--adm-accent);
      outline-offset: 2px;
    }

    /* ══ RESPONSIVE GUTTERS ════════════════════════════════════════════════════
       #view-admin-scoped rules above outrank the plain .admin-section /
       .admin-welcome rules the older stylesheet uses inside its 900px block, so
       the compact spacing has to be restated here through the gutter token.
       ═════════════════════════════════════════════════════════════════════════ */
    @media (max-width: 900px) {
      #view-admin {
        --adm-gutter: .85rem;
      }

      #view-admin .admin-section {
        padding: 1.1rem .9rem;
      }

      #view-admin .admin-welcome {
        padding: 1.25rem var(--adm-gutter) 1rem;
      }

      #view-admin .admin-welcome h2 {
        font-size: 1.15rem;
      }
    }

    @media (max-width: 640px) {
      #view-admin .admin-stat-card {
        gap: .7rem;
        padding: .9rem;
      }

      #view-admin .admin-stat-icon {
        width: 36px;
        height: 36px;
        font-size: 1rem;
      }

      #view-admin .admin-stat-val {
        font-size: 1.3rem;
      }
    }

    @media (prefers-reduced-motion: reduce) {

      #view-admin .admin-tab::before,
      #view-admin .admin-stat-card {
        transition: none;
      }
    }

/* ══ LAST LOGIN ════════════════════════════════════════════════════════════
   Rendered by ksAdmLastLoginCell in dojo-homann-admin-dashboard.v2.js, which
   both rosters call. The colours were inline hex at each of the two render
   sites and they disagreed — one used #16a34a/#f59e0b/#6b7280/#ef4444, the
   other only #16a34a — so the same member could read as urgent on one table
   and neutral on the other.

   They are tokens now, and specifically the tokens tools/verify-theme-token-
   contrast.mjs measures: --ks-success and --ks-warning, which it checks at
   5.51:1 and 5.43:1 on --ks-surface. The literals they replace do not clear
   that bar — #16a34a is 3.05:1 on white and #ef4444 is 3.35:1, both under the
   4.5:1 this platform holds body text to — so the old cells were shipping
   below the standard the rest of the dashboard is held to, twice, in two
   different ways.
   ═════════════════════════════════════════════════════════════════════════ */
#view-admin .adm-lastlogin {
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}

#view-admin .adm-lastlogin-now {
  color: var(--ks-success);
  font-weight: 700;
}

#view-admin .adm-lastlogin-week {
  color: var(--adm-ink-2);
}

#view-admin .adm-lastlogin-month {
  color: var(--adm-ink-3);
}

/* Beyond the activity window. Stated, not alarmed: a member who has not signed
   in for two months is a fact about the dojo, not a fault. */
#view-admin .adm-lastlogin-old {
  color: var(--ks-warning);
}

#view-admin .adm-lastlogin-none {
  color: var(--adm-ink-3);
  /* The dash is information — "never" — so it carries a cursor that says the
     title is worth reading rather than looking like a rendering failure. */
  cursor: help;
}


/* ══════════════════════════════════════════════════════════════════════
   dojo-home-shell.v2.css
   ══════════════════════════════════════════════════════════════════════ */
    /* ══════════════════════════════════════════════════════════════════════════
       HOME SHELL — the first surface built on the semantic theme tokens.

       Loaded last and scoped to #view-home, so every rule here outranks the
       class-level home stylesheets on id specificity alone and nothing can
       reach another view. That is the same technique dojo-admin-dashboard-shell
       .v1.css proved: restyle over the markup that already works, so no view,
       handler, listener or test moves to get a new look.

       It reads only --ks-* names, never a raw colour, which is what makes one
       stylesheet able to render both themes. The home page has until now been
       dark by accident rather than by choice -- the light card shell loads at
       head line 49 and an unconditional -dark override at line 85 simply wins on
       order. Here the theme is a decision the reader or the tenant makes.
       ══════════════════════════════════════════════════════════════════════════ */

    /* ── Page frame ─────────────────────────────────────────────────────────── */
    #view-home {
      background: var(--ks-canvas);
      color: var(--ks-ink);
    }

    /* ══ HERO ═══════════════════════════════════════════════════════════════════
       Nothing here. The hero this file used to dress -- ".hero" with a
       ".hero-lockup" inside it, forced dark in both themes -- is not the markup
       any more: it is .ks-hero / .ks-hero-inner / .ks-hero-copy, styled by
       dojo-tenant-surface-components.v1.css from the theme tokens, which is why
       it follows light and dark correctly.
       Forty lines survived that rewrite as dead rules, matching nothing and
       reading as though the hero were deliberately dark. Repairing the selector
       would have resurrected the old design on top of the current one; the rules
       are gone instead.
       ═══════════════════════════════════════════════════════════════════════════ */

    /* The badge frame carries its own aura and spotlight layers. They are left
       alone; only the box they sit in is given room to breathe. */
    #view-home .home-badge-premium-frame {
      margin: 0 auto;
    }

    /* The frame pulls the image up and down with percentage margins tuned to a
       mark that carries its own transparent padding. The tenant slot behind this
       can hold any image, and with a full-bleed one the negative bottom margin
       drags the line below it up over the artwork. Spacing here is the frame's
       job, not the image's. */
    #view-home .home-badge-premium-frame #home-logo-img {
      max-width: 100%;
      height: auto;
      margin-top: 0;
      margin-bottom: 0;
    }

    #view-home>.hero .hero-lockup+div {
      margin-top: clamp(1rem, 2.5vw, 1.75rem);
    }

    /* ══ CONTENT ════════════════════════════════════════════════════════════════ */
    #view-home .home-light-section {
      background: var(--ks-canvas);
      color: var(--ks-ink);
      padding: clamp(1.75rem, 5vw, 3.5rem) var(--ks-gutter) clamp(2.5rem, 6vw, 4.5rem);
    }

    #view-home .cc-wrap {
      max-width: var(--ks-measure);
      gap: clamp(1.25rem, 3vw, 2rem);
    }

    /* Quiet by design: this line matters only when it is reporting a problem,
       and handleListenerError colours it explicitly when it is. */
    #view-home #db-status {
      color: var(--ks-ink-3);
      padding-top: 0;
      margin-bottom: 0;
    }

    #view-home #db-status:empty {
      display: none;
    }

    /* ── Section headers ────────────────────────────────────────────────────── */
    /* Wraps rather than compressing: at phone widths the title and the "view
       all" link cannot share a line without one of them breaking mid-word. */
    #view-home .cc-events-header {
      display: flex;
      flex-wrap: wrap;
      align-items: center;
      justify-content: space-between;
      gap: .35rem 1rem;
      margin-bottom: .9rem;
      padding-bottom: 0;
      border-bottom: 0;
    }

    #view-home .cc-events-header-left {
      display: flex;
      align-items: center;
      gap: .55rem;
      min-width: 0;
    }

    #view-home .cc-events-header-icon {
      font-size: 1rem;
      line-height: 1;
      flex-shrink: 0;
    }

    #view-home .cc-events-header-title {
      font-family: var(--ks-display);
      font-size: clamp(1.1rem, 1.8vw, 1.25rem);
      font-weight: 700;
      letter-spacing: .01em;
      text-transform: none;
      color: var(--ks-ink);
    }

    #view-home .cc-events-view-all {
      font-size: .8rem;
      font-weight: 600;
      letter-spacing: .02em;
      text-transform: none;
      color: var(--ks-accent-strong);
      text-decoration: none;
      white-space: nowrap;
      cursor: pointer;
      /* Shapes the focus ring, not a fill -- this is a text link. On the control
         scale so the ring agrees with every other focusable thing on the page. */
      border-radius: var(--ks-r-control-sm);
      padding: .3rem .1rem;
      transition: color var(--duration-fast) var(--ease-out);
    }

    #view-home .cc-events-view-all:hover {
      color: var(--ks-ink);
    }

    /* The announcement moved into the shared highlight banner, which owns its
       presentation now. Rules left here would outrank that component on id
       specificity and quietly put the old card treatment back. */

    /* ── Cards ──────────────────────────────────────────────────────────────── */
    #view-home .cc-top-row {
      display: grid;
      /* minmax(0, ...), not a bare 1fr. `1fr` is minmax(AUTO, 1fr), and that
         auto floor is the item's min-content width: the track refuses to go
         below it and hands the overflow to the card, which then paints past the
         right edge of the screen with no way to scroll to it. The two-column
         rule further down has always written minmax(0, ...); the single-column
         phone case — the narrowest viewport, the one with nothing to spare —
         was the only one left without the guard. */
      grid-template-columns: minmax(0, 1fr);
      gap: clamp(1rem, 2vw, 1.25rem);
      /* START, not stretch. This row used to hold three cards whose height came
         from the tallest of them — the calendar — so the Next Event card
         centred ~160px of content inside a 437px box and produced 139px of
         empty space above it and 139px below. Measured on homann 2026-08-14;
         it was the largest single piece of nothing on the page.
         Cards size to their content now. The calendar is naturally the taller
         of the two and no longer imposes that on its neighbour. */
      align-items: start;
    }

    #view-home .cc-card {
      background: var(--ks-surface);
      border: 1px solid var(--ks-line);
      border-radius: var(--radius-lg);
      padding: clamp(1.1rem, 2vw, 1.4rem);
      box-shadow: var(--ks-shadow-1);
      /* Position and scale are deliberately not animated. A card that lifts and
         grows on hover reads as a template; a card whose edge and shadow firm up
         reads as a surface responding. */
      transition:
        box-shadow var(--duration-base) var(--ease-out),
        border-color var(--duration-base) var(--ease-out);
    }

    #view-home .cc-card:hover {
      transform: none;
      border-color: var(--ks-line);
      box-shadow: var(--ks-shadow-2);
    }

    #view-home .cc-card-header {
      display: flex;
      align-items: center;
      justify-content: flex-start;
      text-align: left;
      gap: .55rem;
      margin-bottom: 1rem;
      padding-bottom: .75rem;
      border-bottom: 1px solid var(--ks-line-soft);
    }

    #view-home .cc-card-header-icon {
      font-size: 1rem;
      line-height: 1;
    }

    /* A heading, not a label: natural case at heading size. The tiny
       wide-tracked caps this replaces read as furniture to exactly the
       readers a dojo has most of — kids and grandparents (typography audit,
       2026-08-15). Caps survive only on compact semantic chips. */
    #view-home .cc-card-header-title {
      font-family: var(--ks-display);
      font-size: 1.2rem;
      font-weight: 700;
      letter-spacing: .01em;
      text-transform: none;
      color: var(--ks-ink);
    }

    /* ── Next event ─────────────────────────────────────────────────────────── */
    #view-home .cc-next-event-title {
      font-family: var(--ks-display);
      font-size: clamp(1.25rem, 2vw, 1.5rem);
      font-weight: 700;
      line-height: 1.25;
      color: var(--ks-ink);
      margin-bottom: .2rem;
    }

    /* getEventKindMeta appends one of the cc-badge-* classes, each of which
       carries its own light-on-dark pair. Matched here so a kind still reads on
       a light card; the hue stays distinct through the soft accent fill. */
    #view-home .cc-next-event-badge,
    #view-home .cc-badge-tournament,
    #view-home .cc-badge-practice,
    #view-home .cc-badge-team,
    #view-home .cc-badge-other {
      display: inline-block;
      background: var(--ks-accent-soft);
      color: var(--ks-accent-strong);
      border: 1px solid var(--ks-line);
      border-radius: var(--radius-full);
      padding: .22rem .6rem;
      font-size: .6rem;
      font-weight: 800;
      letter-spacing: .12em;
      text-transform: uppercase;
    }

    #view-home .cc-badge-team {
      background: rgba(23, 92, 211, .1);
      color: var(--ks-info);
    }

    #view-home .cc-next-event-detail {
      display: flex;
      align-items: center;
      justify-content: flex-start;
      text-align: left;
      gap: .5rem;
      font-size: .85rem;
      color: var(--ks-ink-2);
    }

    #view-home .cc-next-event-title,
    #view-home .cc-next-event-empty {
      text-align: left;
    }

    #view-home .cc-next-event-detail-icon {
      opacity: .75;
      flex-shrink: 0;
    }

    #view-home .cc-next-event-empty,
    #view-home .cc-events-empty {
      color: var(--ks-ink-3);
      font-size: .85rem;
    }

    /* ── Mini calendar ──────────────────────────────────────────────────────── */
    #view-home .cc-calendar-nav {
      display: flex;
      align-items: center;
      justify-content: space-between;
      gap: .5rem;
      margin-bottom: .6rem;
    }

    #view-home .cc-calendar-month-label {
      font-family: var(--ks-display);
      font-size: .88rem;
      font-weight: 700;
      letter-spacing: .1em;
      text-transform: uppercase;
      color: var(--ks-ink);
    }

    #view-home .cc-calendar-nav-btn {
      background: transparent;
      border: 1px solid var(--ks-line);
      border-radius: var(--ks-r-control);
      color: var(--ks-ink-2);
      width: 28px;
      height: 28px;
      display: flex;
      align-items: center;
      justify-content: center;
      cursor: pointer;
      transition:
        background var(--duration-fast) var(--ease-out),
        color var(--duration-fast) var(--ease-out);
    }

    #view-home .cc-calendar-nav-btn:hover {
      background: var(--ks-accent-soft);
      color: var(--ks-ink);
    }

    #view-home .cc-calendar-weekdays,
    #view-home .cc-calendar-grid {
      display: grid;
      grid-template-columns: repeat(7, minmax(0, 1fr));
      gap: 2px;
    }

    /* Month paging: the new grid settles in from the direction it was asked
       for. Transform and opacity only, one shot, under 200ms — feedback for
       the page turn, not a show. */
    @keyframes ks-cal-turn-fwd {
      from { opacity: .3; transform: translateX(10px); }
      to { opacity: 1; transform: translateX(0); }
    }

    @keyframes ks-cal-turn-back {
      from { opacity: .3; transform: translateX(-10px); }
      to { opacity: 1; transform: translateX(0); }
    }

    #view-home .cc-calendar-grid.cal-turn-fwd {
      animation: ks-cal-turn-fwd .19s var(--ease-out);
    }

    #view-home .cc-calendar-grid.cal-turn-back {
      animation: ks-cal-turn-back .19s var(--ease-out);
    }

    @media (prefers-reduced-motion: reduce) {
      #view-home .cc-calendar-grid.cal-turn-fwd,
      #view-home .cc-calendar-grid.cal-turn-back {
        animation: none;
      }
    }

    #view-home .cc-calendar-weekday {
      text-align: center;
      font-size: .68rem;
      font-weight: 700;
      letter-spacing: .08em;
      text-transform: uppercase;
      color: var(--ks-ink-3);
      padding-bottom: .4rem;
    }

    /* A month at a glance, not a wall of squares. The cell used to be
       aspect-ratio 1, which at the desktop column width made 82px squares —
       a grid taller than the information it carried, with 11px numerals lost
       in the middle. Rows are now a compact fixed rhythm sized to the
       numeral-plus-indicator they hold, and the numeral is the biggest thing
       in the cell. 44px keeps the touch target honest. */
    #view-home .home-calendar-mini-cell {
      position: relative;
      min-height: 44px;
      display: flex;
      flex-direction: column;
      align-items: center;
      justify-content: center;
      gap: 3px;
      padding: .3rem 0 .25rem;
      background: transparent;
      border: 1px solid transparent;
      border-radius: var(--radius-md);
      color: var(--ks-ink-2);
      font-size: .95rem;
      font-weight: 600;
      font-variant-numeric: tabular-nums;
      cursor: pointer;
      transition:
        background var(--duration-fast) var(--ease-out),
        color var(--duration-fast) var(--ease-out);
    }

    #view-home .home-calendar-mini-cell:hover {
      background: var(--ks-accent-soft);
      color: var(--ks-ink);
    }

    /* Days outside the month stay in the grid so the weeks keep their shape, but
       carry no weight and take no click focus. */
    #view-home .home-calendar-mini-cell.is-empty {
      color: var(--ks-ink-3);
      opacity: .45;
    }

    /* TODAY is the strongest mark on the grid: the numeral sits in a solid
       accent pip. SELECTED is a state the reader created and can clear, so it
       claims the cell's surface instead — soft fill plus ring. The two compose
       on the same day without fighting. */
    #view-home .home-calendar-mini-cell > span:first-child {
      display: inline-grid;
      place-items: center;
      min-width: 1.9em;
      height: 1.9em;
      border-radius: var(--radius-full);
    }

    #view-home .home-calendar-mini-cell.is-today {
      color: var(--ks-ink);
    }

    #view-home .home-calendar-mini-cell.is-today > span:first-child {
      background: var(--ks-accent);
      color: var(--ks-on-accent);
      font-weight: 800;
    }

    #view-home .home-calendar-mini-cell.selected {
      background: var(--ks-accent-soft);
      border-color: var(--ks-accent);
      color: var(--ks-ink);
      font-weight: 800;
    }

    /* Practice and tournament marks differ in SHAPE as well as colour — a
       round dot against a square — so the distinction survives every kind of
       colour vision. The legend draws the same two shapes. */
    #view-home .home-calendar-mini-dot {
      width: 5px;
      height: 5px;
      border-radius: var(--radius-full);
      display: inline-block;
    }

    #view-home .home-calendar-mini-dot--practice {
      background: var(--ks-accent);
    }

    #view-home .home-calendar-mini-dot--event {
      background: #3498db;
      border-radius: 1px;
    }

    #view-home .home-calendar-mini-dots {
      display: inline-flex;
      gap: 3px;
      min-height: 5px;
      line-height: 0;
    }

    #view-home .cc-calendar-legend {
      display: flex;
      flex-wrap: wrap;
      gap: .75rem;
      margin-top: .7rem;
      padding-top: .6rem;
      border-top: 1px solid var(--ks-line-soft);
    }

    #view-home .cc-calendar-legend-item {
      display: inline-flex;
      align-items: center;
      gap: .35rem;
      font-size: .74rem;
      color: var(--ks-ink-3);
      letter-spacing: .04em;
    }

    #view-home .cc-legend-dot {
      width: 6px;
      height: 6px;
      border-radius: var(--radius-full);
    }

    /* Sits on the legend row's far edge: the two marks explain the grid, the
       link leaves it. */
    #view-home .cc-calendar-full-link {
      margin-left: auto;
    }

    /* ── Selected-day banner ────────────────────────────────────────────────── */
    #view-home .cc-calendar-banner {
      display: none;
    }

    #view-home .cc-calendar-banner.show {
      display: block;
      margin-top: .8rem;
      padding: .8rem .9rem;
      background: var(--ks-surface-sunken);
      border: 1px solid var(--ks-line);
      border-radius: var(--radius-md);
    }

    #view-home .cc-calendar-banner-date {
      font-size: .74rem;
      font-weight: 800;
      letter-spacing: .1em;
      text-transform: uppercase;
      color: var(--ks-ink-3);
      margin-bottom: .45rem;
    }

    #view-home .cc-calendar-banner-item {
      display: flex;
      align-items: center;
      gap: .6rem;
      font-size: .92rem;
      color: var(--ks-ink);
      background: transparent;
      padding: .5rem 0;
      border: 0;
      border-top: 1px solid var(--ks-line-soft);
      cursor: pointer;
    }

    #view-home .cc-calendar-banner-item-main {
      cursor: pointer;
    }

    #view-home .cc-calendar-banner-item-main:hover strong,
    #view-home .cc-calendar-banner-item-main:focus-visible strong {
      color: var(--ks-accent-strong);
    }

    #view-home .cc-calendar-banner-item-main:focus-visible {
      outline: 2px solid var(--ks-focus-ring);
      outline-offset: 2px;
      border-radius: var(--radius-sm);
    }

    /* The per-event add-to-calendar, compact inside the day panel. */
    #view-home .cc-calendar-banner-item .ks-add-cal-btn {
      font-size: .58rem;
      padding: .3rem .6rem;
    }

    /* The whole-calendar export sits on the card header's far edge, in the
       same voice as every other card-level action. */
    #view-home .cc-cal-export {
      margin-left: auto;
      background: none;
      border: 0;
    }

    #view-home .cc-calendar-banner-item-main {
      display: flex;
      flex-direction: column;
      gap: .1rem;
      min-width: 0;
      flex: 1 1 auto;
    }

    #view-home .cc-calendar-banner-item-meta {
      font-size: .8rem;
      color: var(--ks-ink-3);
    }

    #view-home .cc-calendar-banner-item-go {
      flex-shrink: 0;
      font-size: .72rem;
      color: var(--ks-ink-3);
    }

    /* The event's type in words, shaped like the Next Up card's chips so the
       two surfaces read as one vocabulary. */
    #view-home .cc-calendar-banner-kind {
      flex-shrink: 0;
      font-size: .62rem;
      font-weight: 800;
      letter-spacing: .08em;
      text-transform: uppercase;
      padding: .22rem .5rem;
      border-radius: var(--radius-full);
      background: var(--ks-accent-soft);
      color: var(--ks-accent-strong);
    }

    #view-home .cc-calendar-banner-kind--event {
      background: color-mix(in oklab, #3498db 14%, transparent);
      color: #21618c;
    }

    #view-home .cc-calendar-banner-empty {
      font-size: .9rem;
      color: var(--ks-ink-3);
    }

    #view-home .cc-calendar-banner-clear {
      margin-top: .5rem;
      background: transparent;
      border: 1px solid var(--ks-line);
      border-radius: var(--radius-full);
      color: var(--ks-ink-2);
      font-size: .7rem;
      font-weight: 700;
      letter-spacing: .08em;
      padding: .28rem .7rem;
      cursor: pointer;
    }

    #view-home .cc-calendar-banner-clear:hover {
      background: var(--ks-accent-soft);
      color: var(--ks-ink);
    }

    /* ── Quick links ────────────────────────────────────────────────────────── */
    #view-home .cc-quick-links {
      display: flex;
      flex-direction: column;
      gap: .2rem;
    }

    #view-home .cc-quick-link {
      display: flex;
      align-items: center;
      justify-content: flex-start;
      text-align: left;
      gap: .7rem;
      padding: .6rem .55rem;
      border-radius: var(--radius-md);
      color: var(--ks-ink-2);
      text-decoration: none;
      font-size: .84rem;
      font-weight: 600;
      cursor: pointer;
      transition:
        background var(--duration-fast) var(--ease-out),
        color var(--duration-fast) var(--ease-out);
    }

    #view-home .cc-quick-link:hover {
      background: var(--ks-accent-soft);
      color: var(--ks-ink);
    }

    #view-home .cc-quick-link-icon {
      width: 26px;
      height: 26px;
      display: inline-flex;
      align-items: center;
      justify-content: center;
      font-size: .9rem;
      background: var(--ks-surface-sunken);
      border-radius: var(--radius-md);
      flex-shrink: 0;
    }

    /* An earlier quicklinks stylesheet painted this #FFFFFF unconditionally,
       which on a light card is white on white -- the label was invisible, not
       merely low contrast. That file has since been removed as dead; the
       explicit colour stays because it is the correct value, not a patch. */
    #view-home .cc-quick-link-label {
      flex: 1;
      min-width: 0;
      color: var(--ks-ink);
      font-size: .84rem;
      font-weight: 600;
      letter-spacing: .01em;
      text-transform: none;
    }

    #view-home .cc-quick-link-chevron {
      color: var(--ks-ink-3);
      font-size: 1rem;
      flex-shrink: 0;
    }

    /* ── Upcoming events ────────────────────────────────────────────────────── */
    #view-home .cc-events-row {
      display: grid;
      grid-template-columns: 1fr;
      gap: clamp(1rem, 2vw, 1.25rem);
      align-items: stretch;
    }

    /* The base rule ships these at opacity 0 and an IntersectionObserver adds
       .cc-revealed to animate them in. Anything below the fold when the observer
       is wired therefore renders as real content the reader cannot see, and the
       row is rebuilt on every snapshot, so it can lose its reveal again later.
       Content is visible first here and the stagger is dropped: a fade-up that
       replays whenever unrelated data changes is exactly the restlessness this
       design language is meant to remove. */
    #view-home .cc-event-card,
    #view-home .cc-event-card.cc-revealed {
      opacity: 1;
      transform: none;
      animation: none;
    }

    /* Centred in the base rule, which leaves a left-aligned icon sitting above
       centred text. One reading edge down the card is both calmer and faster to
       scan, and it matches every other card in the view. */
    #view-home .cc-event-card,
    #view-home .cc-next-event-body {
      text-align: left;
      align-items: stretch;
    }

    /* Both are inline pills, so they stretch to the card width unless told not
       to once the column stops centring its children. */
    #view-home .cc-next-event-badge,
    #view-home .cc-next-event-actions {
      align-self: flex-start;
    }

    #view-home .cc-event-card {
      display: flex;
      flex-direction: column;
      gap: .8rem;
      background: var(--ks-surface);
      border: 1px solid var(--ks-line);
      border-radius: var(--radius-lg);
      padding: 1.1rem;
      box-shadow: var(--ks-shadow-1);
      transition:
        box-shadow var(--duration-base) var(--ease-out),
        border-color var(--duration-base) var(--ease-out);
    }

    #view-home .cc-event-card:hover {
      transform: none;
      box-shadow: var(--ks-shadow-2);
      border-color: var(--ks-line);
    }

    /* Every alignment property the base rules set has to be restated, not only
       the ones being changed: an id selector outranks a class selector per
       property, so anything left undeclared keeps the centred value and the card
       ends up half realigned. flex-direction is the clearest case -- without it
       the icon stacks above the title instead of sitting beside it. */
    #view-home .cc-event-card-top {
      display: flex;
      flex-direction: row;
      align-items: flex-start;
      justify-content: flex-start;
      text-align: left;
      gap: .7rem;
    }

    #view-home .cc-event-card-icon-wrap {
      width: 34px;
      height: 34px;
      display: flex;
      align-items: center;
      justify-content: center;
      background: var(--ks-surface-sunken);
      border-radius: var(--radius-md);
      font-size: 1rem;
      flex-shrink: 0;
    }

    #view-home .cc-event-card-info {
      display: flex;
      flex-direction: column;
      align-items: flex-start;
      gap: .25rem;
      flex: 1;
      min-width: 0;
      text-align: left;
    }

    #view-home .cc-event-card-badge {
      display: inline-block;
      background: var(--ks-accent-soft);
      color: var(--ks-accent-strong);
      border-radius: var(--radius-full);
      padding: .18rem .55rem;
      margin-bottom: .3rem;
      font-size: .56rem;
      font-weight: 800;
      letter-spacing: .12em;
      text-transform: uppercase;
      /* The base rule pins this with align-self, which a parent's align-items
         cannot reach. */
      align-self: flex-start;
    }

    #view-home .cc-event-card-title {
      text-align: left;
    }

    #view-home .cc-event-card-title {
      font-family: var(--ks-display);
      font-size: 1rem;
      font-weight: 700;
      line-height: 1.3;
      color: var(--ks-ink);
    }

    #view-home .cc-event-card-meta {
      display: flex;
      flex-direction: column;
      align-items: flex-start;
      gap: .3rem;
    }

    #view-home .cc-event-card-meta-item {
      display: flex;
      align-items: center;
      justify-content: flex-start;
      text-align: left;
      gap: .45rem;
      font-size: .78rem;
      font-weight: 500;
      color: var(--ks-ink-2);
    }

    #view-home .cc-event-card-meta-icon {
      opacity: .7;
      flex-shrink: 0;
    }

    #view-home .cc-event-card-actions {
      display: flex;
      flex-wrap: wrap;
      justify-content: flex-start;
      gap: .45rem;
      margin-top: auto;
      padding-top: .3rem;
    }

    /* The list variant hardcodes light-on-dark text with !important, which is a
       flat contradiction of a light surface. Matched here so the declarations
       resolve rather than fight; the tokens then answer for both themes. */
    #view-home .upcoming-event-card {
      background: var(--ks-surface) !important;
      border: 1px solid var(--ks-line) !important;
      color: var(--ks-ink) !important;
      box-shadow: var(--ks-shadow-1) !important;
    }

    #view-home .upcoming-event-title,
    #view-home .upcoming-event-name {
      color: var(--ks-ink) !important;
    }

    #view-home .upcoming-event-meta,
    #view-home .upcoming-event-notes {
      color: var(--ks-ink-2) !important;
    }

    #view-home .upcoming-event-date,
    #view-home .upcoming-event-kind,
    #view-home .upcoming-event-kind.kind-practice {
      color: var(--ks-accent-strong) !important;
    }

    /* ── Buttons ────────────────────────────────────────────────────────────── */
    #view-home .cc-btn {
      display: inline-flex;
      align-items: center;
      justify-content: center;
      gap: .35rem;
      border-radius: var(--radius-full);
      padding: .45rem .9rem;
      font-size: .64rem;
      font-weight: 800;
      letter-spacing: .1em;
      text-transform: uppercase;
      cursor: pointer;
      border: 1px solid transparent;
      transition:
        background var(--duration-fast) var(--ease-out),
        border-color var(--duration-fast) var(--ease-out),
        color var(--duration-fast) var(--ease-out);
    }

    #view-home .cc-btn-gold {
      background: var(--ks-accent);
      border-color: var(--ks-accent);
      color: var(--ks-on-accent);
      box-shadow: none;
    }

    #view-home .cc-btn-gold:hover {
      background: var(--ks-accent-strong);
      border-color: var(--ks-accent-strong);
      color: var(--ks-on-accent);
    }

    #view-home .cc-btn-outline {
      background: transparent;
      border-color: var(--ks-line);
      color: var(--ks-ink-2);
    }

    #view-home .cc-btn-outline:hover {
      background: var(--ks-accent-soft);
      border-color: var(--ks-accent);
      color: var(--ks-ink);
    }

    /* ── Team photo ─────────────────────────────────────────────────────────── */



    /* ── Spotlight banner ───────────────────────────────────────────────────── */
    /* This block used to read "styled only so it cannot render as unreadable if
       it is ever given content; it stays hidden until then". A tenant populated
       it with a season line, and the styling written against an empty banner did
       the opposite of what it promised: --ks-ink-2 is a light-page slate, the
       banner is a dark cap, and the sub line rendered at 2.21:1 measured off the
       pixels.

       The banner's own stylesheet was right all along -- #F0F6FC and
       rgba(148,163,184,.85), 7.38:1, theme-independent on purpose. So the sub and
       tag overrides are gone rather than restated: the tag one was
       character-for-character the base rule, and the sub one was the bug.

       --ks-ink-inverse is NOT the fix for the rule that remains. It means "ink
       opposite the CURRENT surface", so it is #FFFFFF in light theme and #050A14
       in dark -- on a band that is dark in both, it disappears half the time.
       That is the same trap the theme-scoped --ks-success and --ks-danger set for
       the footer. A surface with one permanent colour takes a literal. */
    #view-home .ks-spotlight-banner {
      color: #F0F6FC;
    }

    /* ══ RESPONSIVE ═════════════════════════════════════════════════════════════
       Mobile-first, on the four canonical breakpoints. The class-level home
       stylesheets are desktop-first with max-width queries; because every rule
       here carries #view-home, theirs never apply inside this view and the two
       conventions cannot interleave.
       ═══════════════════════════════════════════════════════════════════════════ */

    /* Below md the quick links live in their own card in the flow, so the copy
       that shares the top row is not rendered at all. */
    #view-home .cc-quick-links-desktop {
      display: none;
    }

    #view-home .cc-quick-links-mobile {
      display: block;
    }

    @media (min-width: 640px) {
      #view-home .cc-events-row {
        grid-template-columns: repeat(2, minmax(0, 1fr));
      }

      #view-home .cc-event-card-meta {
        gap: .35rem;
      }
    }

    @media (min-width: 960px) {
      /* Two columns since 2026-08-14, not three. The third card ("Upcoming
         Events") showed events[1..3] from the same list the first card took
         events[0] from, beside a calendar already dotting all of them — one
         dataset, three presentations. Its content moved into Next Up as a
         compact list, which is where a reader looking at the next event
         actually wants "and then what".
         Calendar slightly wider: it has a fixed 7-column grid to fit, while
         Next Up is text that reflows. */
      #view-home .cc-top-row {
        grid-template-columns: minmax(0, 1fr) minmax(0, 1.15fr);
      }

      #view-home .cc-events-row {
        grid-template-columns: repeat(3, minmax(0, 1fr));
      }

      #view-home .cc-quick-links-desktop {
        display: flex;
      }

      #view-home .cc-quick-links-mobile {
        display: none;
      }
    }

    @media (min-width: 1600px) {
      #view-home .home-light-section,
    }

    /* ══ FOCUS ══════════════════════════════════════════════════════════════════ */
    #view-home a:focus-visible,
    #view-home button:focus-visible,
    #view-home .cc-quick-link:focus-visible,
    #view-home .home-calendar-mini-cell:focus-visible {
      outline: 2px solid var(--ks-focus-ring);
      outline-offset: 2px;
      border-radius: var(--ks-r-control);
    }

    /* ══ REDUCED MOTION ═════════════════════════════════════════════════════════ */
    @media (prefers-reduced-motion: reduce) {

      #view-home .cc-card,
      #view-home .cc-event-card,
      #view-home .cc-btn,
      #view-home .cc-quick-link,
      #view-home .cc-calendar-nav-btn,
      #view-home .home-calendar-mini-cell,
      #view-home .cc-events-view-all {
        transition: none;
      }
    }

    /* ══ UPCOMING EVENTS AS THE ROW'S THIRD COLUMN ══════════════════════════════
       The same cards the full-width row rendered, in a column a third the width.
       They become a list: the icon block and the grid go, the type steps down,
       and the actions stay -- Register, Flyer and View Details are real controls
       and a narrower column is no reason to drop them.
       ═══════════════════════════════════════════════════════════════════════════ */
    #view-home .cc-top-row>.cc-events-section {
      display: flex;
      flex-direction: column;
      min-width: 0;
    }

    #view-home .cc-top-row>.cc-events-section .cc-events-row {
      display: flex;
      flex-direction: column;
      gap: 0;
      flex: 1;
    }

    #view-home .cc-top-row>.cc-events-section .cc-event-card {
      background: none;
      border: 0;
      border-top: 1px solid var(--ks-line-soft);
      border-radius: 0;
      box-shadow: none;
      padding: .85rem 0;
      gap: .45rem;
    }

    #view-home .cc-top-row>.cc-events-section .cc-event-card:first-child {
      border-top: 0;
      padding-top: 0;
    }

    #view-home .cc-top-row>.cc-events-section .cc-event-card:hover {
      box-shadow: none;
    }

    #view-home .cc-top-row>.cc-events-section .cc-event-card-icon-wrap {
      display: none;
    }

    #view-home .cc-top-row>.cc-events-section .cc-event-card-title {
      font-size: .92rem;
    }

    #view-home .cc-top-row>.cc-events-section .cc-event-card-meta-item {
      font-size: .72rem;
    }

    #view-home .cc-top-row>.cc-events-section .cc-btn {
      padding: .3rem .65rem;
      font-size: .56rem;
    }

    /* An empty Next Event card takes its own height instead of matching the
       calendar beside it. Stretched, "No upcoming events scheduled" was the
       tallest element on a dojo's front page -- a lot of furniture for a
       sentence. The populated card still stretches, because then the row is
       reporting something. */
    #view-home #cc-next-event-card.is-empty {
      align-self: start;
    }

    #view-home #cc-next-event-card.is-empty .cc-next-event-empty {
      padding: 1.25rem 0 1.5rem;
    }

    #view-home .cc-events-section.is-empty {
      align-self: start;
    }

    /* And a populated one centres what it has in the height the calendar gives
       it. The empty card was fixed by looking at an empty dojo, which left the
       populated one assumed rather than seen: a practice with a date, a time
       and a room is five lines, the calendar beside it is six hundred pixels,
       and .cc-next-event-actions pins its button to the floor. So the card read
       as a heading, a gap of four hundred pixels, and a button.

       Centred rather than shrunk, because three cards of unequal height is a
       worse row than three of equal height -- the card is not too tall, its
       contents were merely all at the top. */
    #view-home #cc-next-event-card:not(.is-empty) .cc-next-event-body {
      justify-content: center;
    }

    #view-home #cc-next-event-card:not(.is-empty) .cc-next-event-actions {
      margin-top: .4rem;
    }

    /* ── Next Up: what follows the headline event ─────────────────────────────
     *
     * Replaces the third column ("Upcoming Events"), which drew events[1..3] as
     * full cards beside a calendar already marking every one of them. These are
     * rows, not cards, because the question they answer — "and then what" — is
     * a glance, not a destination. The destination is "View all" in the header.
     */
    #view-home .cc-next-up-following {
      margin-top: .9rem;
      padding-top: .9rem;
      border-top: 1px solid var(--ks-line);
      display: flex;
      flex-direction: column;
      gap: .35rem;
    }

    #view-home .cc-next-up-following[hidden] {
      display: none;
    }

    #view-home .cc-next-up-following-label {
      font-size: .62rem;
      font-weight: 800;
      letter-spacing: 1.4px;
      text-transform: uppercase;
      color: var(--ks-ink-3);
      margin-bottom: .15rem;
    }

    /* A real <button>, so it is tabbable and operable from the keyboard without
       anything added. The old third column used div/onclick, which is reachable
       by a mouse alone. */
    #view-home .cc-next-up-row {
      display: flex;
      align-items: baseline;
      gap: .6rem;
      width: 100%;
      /* 44px is the touch-target floor; padding gets there without making a
         two-line list feel loose. */
      min-height: 44px;
      padding: .45rem .55rem;
      background: none;
      border: 1px solid transparent;
      border-radius: var(--radius-md, 10px);
      text-align: left;
      cursor: pointer;
      font: inherit;
      color: inherit;
      transition: background .15s ease, border-color .15s ease;
    }

    #view-home .cc-next-up-row:hover {
      background: var(--ks-surface-sunken);
      border-color: var(--ks-line);
    }

    #view-home .cc-next-up-row:focus-visible {
      outline: 2px solid var(--ks-focus-ring, var(--accent));
      outline-offset: 2px;
    }

    #view-home .cc-next-up-row-badge {
      flex-shrink: 0;
      font-size: .58rem;
      font-weight: 800;
      letter-spacing: .8px;
      text-transform: uppercase;
      padding: .18rem .4rem;
      border-radius: 999px;
      /* A shared column, not content width: TOURNAMENT is twice as wide as
         TEAM, and without a common measure every row's title started at a
         different x. Sized to the widest label the kind map produces
         (TOURNAMENT at 800 weight with .8px tracking, plus the pill's own
         padding), em-based so it scales with the badge's type; a genuinely
         longer future label simply widens its one pill rather than
         truncating. */
      min-width: 9.6em;
      text-align: center;
    }

    #view-home .cc-next-up-row-main {
      display: flex;
      flex-direction: column;
      gap: .1rem;
      /* min-width:0 so a long event title ellipsises instead of forcing the row
         wider than the card — the same failure the nav brand had. */
      min-width: 0;
      flex: 1;
    }

    #view-home .cc-next-up-row-title {
      font-size: .82rem;
      font-weight: 700;
      color: var(--ks-ink);
      overflow: hidden;
      text-overflow: ellipsis;
      white-space: nowrap;
    }

    #view-home .cc-next-up-row-meta {
      font-size: .7rem;
      color: var(--ks-ink-3);
      overflow: hidden;
      text-overflow: ellipsis;
      white-space: nowrap;
    }

    /* The header now carries an action beside its title. */
    #view-home .cc-card-header {
      align-items: center;
    }

    /* It is an <h2> now — heading order on the home view runs h1 (hero) -> h2
       (card) — so ONLY the browser's default heading margin is cleared. The
       first attempt at this also set font-size/weight/letter-spacing to
       `inherit`, which did not "keep the treatment identical": it threw the
       treatment away and the card titles rendered as plain sentence-case text.
       The look lives on .cc-card-header-title above and must reach the h2
       unchanged. */
    #view-home .cc-card-header h2.cc-card-header-title {
      margin: 0;
    }

    #view-home .cc-card-header #cc-next-up-view-all {
      margin-left: auto;
    }

    /* ── Team Updates ─────────────────────────────────────────────────────────
     *
     * The spotlight and the announcement under one heading, at the same measure
     * as the cards above them.
     *
     * They were always built to join — the banner carries a rounded top and no
     * bottom border so it sits ON the highlight — but the pair read as an
     * island: a 900px slab beneath a full-measure row, with nothing naming it.
     * The heading and the shared width are the whole change. Every style, icon,
     * animation and size an admin has chosen still applies, because none of
     * those rules are touched here.
     */
    /* Its own gutter, because this section is NOT inside .home-light-section.
     *
     * Structural fact found while aligning it, and pre-existing rather than
     * introduced here: the spotlight and the highlight have always been
     * siblings of .home-light-section in .view, not children of it — the
     * `/.home-light-section` comment further down the file has been mismatched
     * for some time. So they never received that section's gutter padding, and
     * a max-width alone only LOOKED right on desktop, where the measure is
     * narrower than the viewport and centring supplies the inset by accident.
     * At 375px it went edge to edge while the cards above stayed inset 16px.
     *
     * `calc(100% - 2 * gutter)` capped at the measure is what .home-light-section
     * + .cc-wrap produce together, so this tracks the cards at every width
     * instead of matching them at one. */
    #view-home .ks-team-updates {
      width: calc(100% - 2 * var(--ks-gutter));
      max-width: var(--ks-measure);
      margin: clamp(1.75rem, 4vw, 2.75rem) auto 0;
    }

    /* The banner keeps its own look and stops being a narrower island. Its top
       margin is now the section's job, so it does not add a second gap under
       the heading it belongs to.
       WIDTH MATTERS AS MUCH AS MAX-WIDTH: the banner carries
       `width: calc(100% - 2 * var(--ks-gutter))` from when it was a direct
       child of the full-bleed section and had to inset itself. Inside a section
       that already sits at the measure, that gutter applies a SECOND time —
       measured 1120px at left 80 against the announcement's 1200 at left 40,
       which is exactly the inset that made it read as a separate island. */
    #view-home .ks-team-updates .ks-spotlight-banner {
      max-width: none;
      width: 100%;
      margin-top: 0;
      margin-left: 0;
      margin-right: 0;
    }

    #view-home .ks-team-updates .ks-highlight {
      max-width: none;
      margin-top: 0;
      /* The same second-gutter the banner note above describes, one element
         down: .ks-highlight pads var(--ks-gutter) for the full-bleed case, and
         inside this section — which already sits at the measure — that inset
         made the card 40px narrower than the banner sitting on top of it
         (measured 1120 against 1200 at 1440, and the mismatch survived at
         every width). The pair now share their edges. */
      padding-left: 0;
      padding-right: 0;
    }

    /* THE COLLAPSE RULE THAT USED TO BE HERE IS GONE, and the reason is worth
       keeping so it is not reintroduced.

       It hid the whole section when there was no spotlight and no announcement
       — reasonable-looking, and wrong: .ks-highlight lives in this section and
       contains #btn-upload-team, the admin's control for the team photograph.
       On a dojo with nothing announced, an administrator could no longer change
       or add the photo, and the only symptom was a button that was not there.
       Caught by tests/media/home-image.spec.ts, not by looking.

       HIDING CHROME MUST NEVER HIDE A CONTROL. The children already hide
       themselves when they have nothing to say, so an empty section costs a
       heading and the photo slot — which is honest, because the photo is
       content and the upload control has to be reachable precisely when there
       is nothing there yet.

       If a lone heading is ever worth removing, it has to be done from the
       renderers, which know whether an admin is present, rather than from a
       selector that cannot. */

    /* "How soon" as quiet metadata riding the date it derives from. */
    #view-home .cc-next-event-rel {
      color: var(--ks-ink-3);
      font-weight: 600;
    }


/* ══════════════════════════════════════════════════════════════════════
   dojo-events-shell.v1.css
   ══════════════════════════════════════════════════════════════════════ */
    /* ══════════════════════════════════════════════════════════════════════════
       EVENTS SHELL — the Events view on the semantic theme tokens.

       Scoped to #view-find-tournaments and loaded last, so it outranks the
       class-level stylesheets above on id specificity and cannot reach another
       view. The same technique dojo-home-shell.v2.css uses.

       The listing, seminar and hotel cards are built in JavaScript from a long
       set of legacy class names, and rewriting that markup would mean rewriting
       three renderers at once. Mapping those classes onto the tokens instead
       gets the whole view onto the design system without moving a single
       element, which is both smaller and reversible.
       ══════════════════════════════════════════════════════════════════════════ */

    #view-find-tournaments {
      background: var(--ks-canvas);
      color: var(--ks-ink);
    }

    #view-find-tournaments .ti-content-wrap,
    #view-resources .ti-content-wrap {
      background: var(--ks-canvas);
      max-width: var(--ks-measure);
      margin: 0 auto;
      padding: clamp(1.75rem, 4vw, 2.75rem) var(--ks-gutter) var(--ks-section-gap);
      display: flex;
      flex-direction: column;
      gap: clamp(1.25rem, 3vw, 2rem);
    }

    /* ── Section shells ─────────────────────────────────────────────────────── */
    #view-find-tournaments .ti-section,
    #view-resources .ti-section,
    #view-find-tournaments .ti-prem-section,
    #view-resources .ti-prem-section {
      background: var(--ks-surface);
      border: 1px solid var(--ks-line);
      border-radius: var(--radius-lg);
      box-shadow: var(--ks-shadow-1);
      padding: clamp(1.1rem, 2.5vw, 1.6rem);
      margin: 0;
    }

    #view-find-tournaments .ti-section-hdr,
    #view-resources .ti-section-hdr,
    #view-find-tournaments .ti-prem-hdr,
    #view-resources .ti-prem-hdr {
      display: flex;
      align-items: center;
      gap: .75rem;
      margin-bottom: 1rem;
      padding-bottom: .75rem;
      border-bottom: 1px solid var(--ks-line-soft);
    }

    #view-find-tournaments .ti-section-hdr h3,
    #view-resources .ti-section-hdr h3,
    #view-find-tournaments .ti-prem-hdr-text h3,
    #view-resources .ti-prem-hdr-text h3 {
      font-family: var(--ks-display);
      font-size: clamp(.95rem, 1.8vw, 1.1rem);
      font-weight: 700;
      letter-spacing: .12em;
      text-transform: uppercase;
      color: var(--ks-ink);
      margin: 0;
    }

    #view-find-tournaments .ti-section-desc,
    #view-resources .ti-section-desc,
    #view-find-tournaments .ti-prem-hdr-text p,
    #view-resources .ti-prem-hdr-text p {
      font-size: .78rem;
      color: var(--ks-ink-2);
      margin: .25rem 0 0;
    }

    #view-find-tournaments .ti-section-hdr svg,
    #view-resources .ti-section-hdr svg,
    #view-find-tournaments .ti-prem-hdr-icon,
    #view-resources .ti-prem-hdr-icon {
      color: var(--ks-accent-strong);
      flex-shrink: 0;
    }

    /* ── Reference link cards ───────────────────────────────────────────────── */
    #view-find-tournaments .ti-card,
    #view-resources .ti-card {
      background: var(--ks-surface-sunken);
      border: 1px solid var(--ks-line);
      border-radius: var(--radius-md);
      color: var(--ks-ink);
    }

    #view-find-tournaments .ti-card:hover,
    #view-resources .ti-card:hover {
      border-color: var(--ks-accent);
      background: var(--ks-accent-soft);
    }

    #view-find-tournaments .ti-card-title,
    #view-resources .ti-card-title {
      color: var(--ks-ink);
      font-weight: 700;
    }

    #view-find-tournaments .ti-card-desc,
    #view-resources .ti-card-desc {
      color: var(--ks-ink-2);
    }

    #view-find-tournaments .ti-card-arrow,
    #view-resources .ti-card-arrow {
      color: var(--ks-accent-strong);
    }

    /* ── Event cards ────────────────────────────────────────────────────────── */
    #view-find-tournaments .event-card {
      background: var(--ks-surface);
      border: 1px solid var(--ks-line);
      border-radius: var(--radius-lg);
      box-shadow: var(--ks-shadow-1);
      color: var(--ks-ink);
    }

    /* The next event is marked by its accent edge rather than a different fill,
       so a row of cards still reads as one set. */
    #view-find-tournaments .event-card.card-next {
      border-left: 3px solid var(--ks-accent);
    }

    #view-find-tournaments .premium-event-name {
      font-family: var(--ks-display);
      font-size: clamp(1.05rem, 2vw, 1.25rem);
      font-weight: 700;
      color: var(--ks-ink);
    }

    #view-find-tournaments .premium-event-meta,
    #view-find-tournaments .premium-meta-item,
    #view-find-tournaments .premium-event-desc {
      color: var(--ks-ink-2);
    }

    /* The description panel carries its own background, and this file gave it
       themed INK while leaving that background at a fixed #F8FAFC. In dark theme
       the ink went light and the panel stayed near-white: 2.17:1. A surface and
       the text on it have to follow the same rule, or neither is right. */
    #view-find-tournaments .premium-event-desc {
      background: var(--ks-surface-sunken);
    }

    /* ── The one Up next badge ──────────────────────────────────────────────
       In normal flow inside the card's copy column, never absolutely offset
       over the card edge: the straddling version was clipped by whatever
       happened to sit above the card. In flow, nothing can clip it at any
       width, theme, or name length. */
    #view-find-tournaments .premium-next-badge {
      /* A kicker, not a sticker: part of the content hierarchy, sitting where
         a section eyebrow sits, in the tenant's accent. */
      display: inline-flex;
      align-items: center;
      gap: .35rem;
      margin: 0 0 .3rem;
      color: var(--ks-accent-strong);
      font-size: .68rem;
      font-weight: 800;
      letter-spacing: .12em;
      text-transform: uppercase;
      line-height: 1.4;
      white-space: nowrap;
    }

    #view-find-tournaments .premium-next-badge .ks-icon {
      width: 14px;
      height: 14px;
      flex-shrink: 0;
    }

    /* ── Flyer thumbnails are artwork ───────────────────────────────────────
       The whole composition matters on a flyer -- text, sponsors, the lot --
       so it letterboxes inside a fixed frame instead of being cropped to fill
       it. The frame is constant, so nothing shifts as images load. Hotel
       photography keeps object-fit: cover; a crop is legitimate there. */
    #view-find-tournaments .ks-flyer-thumb {
      width: 200px;
      height: 130px;
      object-fit: contain;
      background: var(--ks-surface-sunken);
      border: 1px solid var(--ks-line-soft);
      border-radius: var(--radius-md);
      flex-shrink: 0;
    }

    /* No flyer yet: the SAME frame, holding the record type's glyph, so every
       card carries equal media weight whether or not artwork is uploaded. */
    #view-find-tournaments .ks-flyer-thumb-empty {
      display: flex;
      align-items: center;
      justify-content: center;
      color: var(--ks-ink-3);
      /* Restrained: it keeps the media column's width so titles align across
         cards, but does not pretend to be a photograph. */
      height: 88px;
    }

    #view-find-tournaments .ks-flyer-thumb-empty .ks-icon {
      width: 34px;
      height: 34px;
    }

    /* ── The patch pointer ──────────────────────────────────────────────────
       A quiet meta chip that jumps to the canonical patch cards under
       Resources. A button, because it navigates inside the app. */
    #view-find-tournaments .ks-patch-hint {
      display: inline-flex;
      align-items: center;
      padding: .18rem .6rem;
      border: 1px solid var(--ks-line);
      border-radius: var(--radius-full);
      background: none;
      color: var(--ks-ink-2);
      font-size: .68rem;
      font-weight: 700;
      letter-spacing: .04em;
      cursor: pointer;
      transition: border-color var(--duration-fast) var(--ease-out), color var(--duration-fast) var(--ease-out);
    }

    #view-find-tournaments .ks-patch-hint:hover,
    #view-find-tournaments .ks-patch-hint:focus-visible {
      border-color: var(--ks-accent);
      color: var(--ks-accent-strong);
    }

    #view-find-tournaments .ks-patch-hint:focus-visible {
      outline: 2px solid var(--ks-focus-ring);
      outline-offset: 1px;
    }

    /* ── RSVP panel ─────────────────────────────────────────────────────────── */
    /* Its own quiet surface inside the card: it is a question being asked, not
       another fact about the event. */
    #view-find-tournaments .ti-listing-rsvp-panel,
    #view-resources .ti-listing-rsvp-panel {
      background: var(--ks-surface-sunken);
      border: 1px solid var(--ks-line);
      border-radius: var(--radius-md);
      padding: .8rem;
      /* Same offset from the actions row and the same right edge on every
         card type. The seminar panel used to carry its own wrapper with a
         520px cap and its own margin, which is why two cards' panels never
         lined up. One class, one geometry. */
      margin-top: 1rem;
      width: 100%;
    }

    /* ── Sprite icons in the card's fact lines ──────────────────────────────
       An SVG <use> has no intrinsic size, so every inline context states one.
       1em keeps each glyph on the cap height of the text beside it. */
    #view-find-tournaments .premium-event-meta .ks-icon,
    #view-find-tournaments .premium-hotel-line .ks-icon,
    #view-find-tournaments .premium-hotel-sub-title .ks-icon,
    #view-find-tournaments .premium-hotel-added .ks-icon,
    #view-find-tournaments .hotel-meta .ks-icon,
    #view-find-tournaments .btn .ks-icon {
      width: 1em;
      height: 1em;
      vertical-align: -0.14em;
      display: inline-block;
      flex-shrink: 0;
    }

    #view-find-tournaments .premium-hotel-icon .ks-icon,
    #view-find-tournaments .hotel-icon .ks-icon {
      width: 18px;
      height: 18px;
      display: block;
    }

    /* ── Empty states and hotels ────────────────────────────────────────────── */
    #view-find-tournaments .ti-prem-empty,
    #view-resources .ti-prem-empty {
      color: var(--ks-ink-3);
      background: var(--ks-surface-sunken);
      border: 1px solid var(--ks-line-soft);
      border-radius: var(--radius-md);
    }

    #view-find-tournaments .ti-prem-empty-title,
    #view-resources .ti-prem-empty-title {
      color: var(--ks-ink);
    }

    #view-find-tournaments .premium-hotel-panel,
    #view-find-tournaments .premium-hotel-block {
      background: var(--ks-surface-sunken);
      border: 1px solid var(--ks-line);
      border-radius: var(--radius-md);
      color: var(--ks-ink);
    }

    #view-find-tournaments .premium-hotel-label,
    #view-find-tournaments .premium-hotel-meta {
      color: var(--ks-ink-2);
    }

    /* ══ WHAT THE DARK CARD FILE USED TO OWN ════════════════════════════════════
       dojo-tournament-info-event-seminar-dark-cards.v1.css set all of this with
       !important. It is emptied, so these are the real definitions now.
       ═══════════════════════════════════════════════════════════════════════════ */

    #view-find-tournaments .premium-btn,
    #view-find-tournaments .premium-btn-outline {
      border-radius: var(--radius-full);
      font-weight: 700;
      letter-spacing: .06em;
    }

    #view-find-tournaments .premium-btn-outline {
      background: var(--ks-surface);
      border: 1px solid var(--ks-line);
      color: var(--ks-ink-2);
    }

    #view-find-tournaments .premium-btn-outline:hover {
      border-color: var(--ks-accent);
      background: var(--ks-accent-soft);
      color: var(--ks-ink);
    }

    #view-find-tournaments .premium-btn:focus-visible,
    #view-find-tournaments .premium-btn-outline:focus-visible,
    #view-find-tournaments .ti-card:focus-visible,
    #view-resources .ti-card:focus-visible,
    #view-find-tournaments .event-card:focus-visible {
      outline: 2px solid var(--ks-focus-ring);
      outline-offset: 2px;
    }

    /* The add buttons are the section's primary action, so they are the one
       filled control in it. */
    #view-find-tournaments .ti-prem-add-btn,
    #view-resources .ti-prem-add-btn {
      background: var(--ks-accent);
      border: 1px solid var(--ks-accent);
      border-radius: var(--radius-full);
      color: var(--ks-on-accent);
      font-weight: 800;
      letter-spacing: .08em;
    }

    #view-find-tournaments .ti-prem-add-btn:hover,
    #view-resources .ti-prem-add-btn:hover {
      background: var(--ks-accent-strong);
      border-color: var(--ks-accent-strong);
      color: var(--ks-surface);
    }

    :root[data-theme="dark"] #view-find-tournaments .ti-prem-add-btn:hover,
    :root[data-theme="dark"] #view-resources .ti-prem-add-btn:hover {
      color: var(--ks-on-accent);
    }

    #view-find-tournaments .premium-hotel-sub,
    #view-find-tournaments .premium-hotel-empty {
      background: var(--ks-surface-sunken);
      border: 1px solid var(--ks-line-soft);
      border-radius: var(--radius-md);
      color: var(--ks-ink-2);
    }

    #view-find-tournaments .premium-hotel-sub-title,
    #view-find-tournaments .premium-hotel-name {
      color: var(--ks-ink);
      font-weight: 700;
    }

    #view-find-tournaments .premium-hotel-line,
    #view-find-tournaments .premium-hotel-icon {
      color: var(--ks-ink-2);
    }

    /* Same mismatch as the description panel above: the hotel card is painted a
       fixed #FFFFFF by dojo-premium-hotel-lodging-desktop.v1.css, while its name
       and address were themed here. In dark theme "Lincoln Court Hotel" was
       #E0DCD2 on white -- 1.37:1, the worst reading on the tenant, and invisible
       only to the readers who use dark mode. */
    #view-find-tournaments .premium-hotel-card {
      background: var(--ks-surface);
      border-color: var(--ks-line);
    }

    /* "Added by" / "Posted by". Both were a fixed #64748B -- one in a stylesheet,
       one written inline by the module that builds the card. On the light card
       that reads fine; once the card follows the theme it is 3.9:1 on the dark
       one. The inline one now carries a class, so both are the same thing said
       once. */
    #view-find-tournaments .premium-hotel-added,
    #view-find-tournaments .premium-event-added {
      color: var(--ks-ink-3);
    }

    #view-find-tournaments .premium-event-added {
      font-size: .95rem;
      font-weight: 700;
      letter-spacing: .5px;
      margin-top: .5rem;
    }

    #view-find-tournaments .ti-bottom-banner,
    #view-resources .ti-bottom-banner {
      background: var(--ks-surface-sunken);
      border: 1px solid var(--ks-line);
      border-radius: var(--radius-lg);
      color: var(--ks-ink-2);
    }

    /* The badge sat over the card's own top edge and was clipped by it. */
    #view-find-tournaments .event-card {
      position: relative;
      overflow: visible;
    }

    /* ══ WHAT THE LIVE CONTRAST PROBE FOUND ═════════════════════════════════════
       Three pairs the shell had not restated, all reported by
       tests/design/theme-contrast.spec.ts against the rendered view rather than
       found by reading these stylesheets.
       ═══════════════════════════════════════════════════════════════════════════ */

    /* The destructive action used the raw legacy red, which reaches only 3.94:1
       on the dark surface and 3.83:1 on its own light tint -- the one control on
       the page where being sure what it says matters most. --ks-danger is the
       contrast-checked value for each theme. */
    #view-find-tournaments .btn-danger {
      background: transparent;
      border: 1px solid var(--ks-danger);
      color: var(--ks-danger);
    }

    #view-find-tournaments .btn-danger:hover {
      background: var(--ks-danger);
      color: var(--ks-surface);
    }

    /* The section header carried a grey band of its own, so the description on it
       read at 2.25:1. The header belongs to the card it sits in. */
    #view-find-tournaments .ti-prem-hdr,
    #view-resources .ti-prem-hdr,
    #view-find-tournaments .ti-section-hdr,
    #view-resources .ti-section-hdr {
      background: none;
      border-radius: 0;
    }

    /* The registration sub-headings were the raw brand gold, which is a fill and
       not a text colour: 2.29:1 on white.
       dojo-tournament-info-dark-shell-cards.v1.css sets it !important at
       `.ti-section h5`, so this has to match that selector's specificity and its
       !important to win. That file is not emptied like its sibling was, because
       it still carries the colour-coded borders the reference cards use. */
    #view-find-tournaments .ti-section h5,
    #view-resources .ti-section h5,
    #view-find-tournaments h5 {
      color: var(--ks-ink-2) !important;
      font-size: .68rem;
      font-weight: 800;
      letter-spacing: .14em;
      text-transform: uppercase;
    }

    /* ── The quiet pointer to All Resources ─────────────────────────────────
       One line where two permanent reference directories used to sit. */
    #view-find-tournaments .ti-resource-pointer,
    #view-resources .ti-resource-pointer {
      max-width: var(--ks-measure);
      margin: 0 auto;
      padding: .4rem 0 1.6rem;
      text-align: center;
    }

    #view-find-tournaments .ti-resource-pointer a,
    #view-resources .ti-resource-pointer a {
      color: var(--ks-ink-2);
      font-size: .88rem;
      font-weight: 700;
      cursor: pointer;
      text-decoration: none;
      border-bottom: 1px solid var(--ks-line);
      padding-bottom: 2px;
      transition: color var(--duration-fast) var(--ease-out), border-color var(--duration-fast) var(--ease-out);
    }

    #view-find-tournaments .ti-resource-pointer a:hover,
    #view-resources .ti-resource-pointer a:hover,
    #view-find-tournaments .ti-resource-pointer a:focus-visible,
    #view-resources .ti-resource-pointer a:focus-visible {
      color: var(--ks-accent-strong);
      border-color: var(--ks-accent);
    }

    #view-find-tournaments .ti-resource-pointer a:focus-visible,
    #view-resources .ti-resource-pointer a:focus-visible {
      outline: 2px solid var(--ks-focus-ring);
      outline-offset: 3px;
    }

    /* Sub-group label inside a resources section (AAU / NKF tournaments).
       Token ink, so it reads on both the light card and the dark glass card. */
    #view-find-tournaments .ti-group-label,
    #view-resources .ti-group-label {
      font-size: .8rem;
      font-weight: 800;
      color: var(--ks-ink);
      letter-spacing: 1px;
      text-transform: uppercase;
      margin: 0 0 .75rem;
    }


/* ══════════════════════════════════════════════════════════════════════
   dojo-schedule-shell.v1.css
   ══════════════════════════════════════════════════════════════════════ */
    /* ══════════════════════════════════════════════════════════════════════════
       SCHEDULE SHELL — the Schedule view on the semantic theme tokens.

       Scoped to #view-schedule and loaded last. Four -dark stylesheets used to
       set this view's colours with !important; they are emptied, so these are the
       real definitions now. Their structural siblings are untouched.

       On the name: this is the team's calendar of dated events, and it is called
       Schedule rather than Class Schedule on purpose. There is no recurring class
       data in the product yet, so a weekly grid would be a promise nothing can
       keep. It stays a real calendar until that capability exists.
       ══════════════════════════════════════════════════════════════════════════ */

    #view-schedule {
      background: var(--ks-canvas);
      color: var(--ks-ink);
    }

    #view-schedule .page-light-content {
      background: var(--ks-canvas);
      max-width: var(--ks-measure);
      margin: 0 auto;
      padding: clamp(1.5rem, 4vw, 2.5rem) var(--ks-gutter) var(--ks-section-gap);
    }

    /* ── Calendar shell ─────────────────────────────────────────────────────── */
    #view-schedule .home-calendar {
      background: var(--ks-surface);
      border: 1px solid var(--ks-line);
      border-radius: var(--radius-lg);
      box-shadow: var(--ks-shadow-1);
    }

    #view-schedule .home-calendar-header {
      border-bottom: 1px solid var(--ks-line-soft);
    }

    #view-schedule .home-calendar-title {
      font-family: var(--ks-display);
      font-weight: 700;
      letter-spacing: .1em;
      text-transform: uppercase;
      color: var(--ks-ink);
    }

    #view-schedule .home-calendar-sub {
      color: var(--ks-ink-2);
    }

    /* ── Mini calendar ──────────────────────────────────────────────────────── */
    /* The base sets this !important, so nothing without it can win. */
    #view-schedule .sch-month-nav,
    #view-schedule #sch-cal-month {
      color: var(--ks-ink) !important;
      font-family: var(--ks-display);
      font-weight: 700;
      letter-spacing: .06em;
    }

    #view-schedule .sch-month-nav .btn.btn-ghost {
      background: transparent;
      border: 1px solid var(--ks-line);
      border-radius: var(--ks-r-control);
      color: var(--ks-ink-2);
    }

    #view-schedule .sch-month-nav .btn.btn-ghost:hover {
      background: var(--ks-accent-soft);
      color: var(--ks-ink);
    }

    #view-schedule .home-calendar-mini {
      background: var(--ks-surface-sunken);
      border: 1px solid var(--ks-line-soft);
      border-radius: var(--radius-md);
    }

    #view-schedule .home-calendar-mini-weekday {
      color: var(--ks-ink-3);
      font-weight: 700;
      letter-spacing: .06em;
    }

    #view-schedule .home-calendar-mini-cell {
      background: transparent;
      border: 1px solid transparent;
      border-radius: var(--radius-md);
      color: var(--ks-ink-2);
    }

    #view-schedule .home-calendar-mini-cell:hover {
      background: var(--ks-accent-soft);
      color: var(--ks-ink);
    }

    /* Schedule names these states .other-month and .today. The home page calls
       the same two .is-empty and .is-today, and using its names here matched
       nothing -- so the base rules kept their raw colours and the today cell read
       at 1.48:1 in the dark theme. */
    #view-schedule .home-calendar-mini-cell.other-month {
      background: transparent;
      color: var(--ks-ink-3);
      opacity: .45;
    }

    #view-schedule .home-calendar-mini-cell.today {
      background: var(--ks-accent-soft);
      color: var(--ks-ink);
      font-weight: 800;
      border-color: var(--ks-accent);
    }

    #view-schedule .home-calendar-mini-cell.selected {
      background: var(--ks-accent);
      border-color: var(--ks-accent);
      color: var(--ks-on-accent);
      font-weight: 800;
    }

    /* ── Event list ─────────────────────────────────────────────────────────── */
    #view-schedule .sch-panel-header {
      border-bottom: 1px solid var(--ks-line-soft);
    }

    #view-schedule .sch-panel-date {
      font-family: var(--ks-display);
      font-weight: 700;
      color: var(--ks-ink);
    }

    #view-schedule .sch-panel-count {
      color: var(--ks-ink-3);
    }

    #view-schedule .home-calendar-item {
      background: var(--ks-surface);
      border: 1px solid var(--ks-line);
      border-radius: var(--radius-md);
      color: var(--ks-ink);
      transition:
        box-shadow var(--duration-base) var(--ease-out),
        border-color var(--duration-base) var(--ease-out);
    }

    #view-schedule .home-calendar-item:hover {
      box-shadow: var(--ks-shadow-2);
      border-color: var(--ks-accent);
    }

    /* A tournament is marked by its edge rather than a different fill, so the
       list still reads as one list. */
    #view-schedule .home-calendar-item.sch-tournament {
      border-left: 3px solid var(--ks-accent);
    }

    #view-schedule .home-calendar-date {
      background: var(--ks-surface-sunken);
      border: 1px solid var(--ks-line-soft);
      border-radius: var(--radius-md);
      color: var(--ks-ink);
    }

    /* The day number inside the date chip. Missed on the first pass because I
       restated the month abbreviation beside it and not this. */
    #view-schedule .home-calendar-date-day {
      color: var(--ks-ink);
      font-weight: 800;
    }

    #view-schedule .home-calendar-date-mon {
      color: var(--ks-accent-strong);
      font-weight: 800;
      letter-spacing: .1em;
      text-transform: uppercase;
    }

    #view-schedule .home-calendar-name,
    #view-schedule .home-calendar-title-text,
    #view-schedule .home-calendar-item-title {
      font-family: var(--ks-display);
      font-weight: 700;
      color: var(--ks-ink);
    }

    #view-schedule .home-calendar-meta,
    #view-schedule .home-calendar-item-meta,
    #view-schedule .home-calendar-notes {
      color: var(--ks-ink-2);
    }

    #view-schedule .home-calendar-empty,
    #view-schedule .home-calendar-reminder {
      color: var(--ks-ink-3);
    }

    #view-schedule .home-calendar-badge-today,
    #view-schedule .home-calendar-badge-reminder {
      background: var(--ks-accent-soft);
      color: var(--ks-accent-strong);
      border: 1px solid var(--ks-line);
      border-radius: var(--radius-full);
    }

    /* ── Actions and quick links ────────────────────────────────────────────── */
    #view-schedule .sch-action-link,
    #view-schedule .sch-quick-link,
    #view-schedule .sch-clear-btn {
      background: var(--ks-surface);
      border: 1px solid var(--ks-line);
      border-radius: var(--radius-full);
      color: var(--ks-ink-2);
      font-weight: 700;
      letter-spacing: .06em;
      text-decoration: none;
      transition:
        background var(--duration-fast) var(--ease-out),
        border-color var(--duration-fast) var(--ease-out),
        color var(--duration-fast) var(--ease-out);
    }

    #view-schedule .sch-action-link:hover,
    #view-schedule .sch-quick-link:hover,
    #view-schedule .sch-clear-btn:hover {
      border-color: var(--ks-accent);
      background: var(--ks-accent-soft);
      color: var(--ks-ink);
    }

    /* Register is the one action worth filling: it is the thing the page is for. */
    #view-schedule .sch-action-register {
      background: var(--ks-accent);
      border-color: var(--ks-accent);
      color: var(--ks-on-accent);
    }

    #view-schedule .sch-action-register:hover {
      background: var(--ks-accent-strong);
      border-color: var(--ks-accent-strong);
      color: var(--ks-surface);
    }

    :root[data-theme="dark"] #view-schedule .sch-action-register:hover {
      color: var(--ks-on-accent);
    }

    #view-schedule .home-calendar-mini-cell:focus-visible,
    #view-schedule .sch-action-link:focus-visible,
    #view-schedule .sch-quick-link:focus-visible,
    #view-schedule .sch-clear-btn:focus-visible,
    #view-schedule .btn:focus-visible {
      outline: 2px solid var(--ks-focus-ring);
      outline-offset: 2px;
      box-shadow: none;
    }

    @media (prefers-reduced-motion: reduce) {

      #view-schedule .home-calendar-item,
      #view-schedule .sch-action-link,
      #view-schedule .sch-quick-link,
      #view-schedule .sch-clear-btn {
        transition: none;
      }
    }
