/* ===========================================================================
   AniceTool brand tokens
   ---------------------------------------------------------------------------
   GENERATED FILE - DO NOT EDIT.

   Source:   .claude/brand/palette.py      (colour)
             .claude/brand/brand-extras.css (everything else)
   Rebuild:  python3 .claude/brand/build-brand-css.py
   Verify:   python3 .claude/brand/check-contrast.py

   Brand:    Primary #0066FF Electric Blue - actions, headers, active states
             Accent  #10B981 Emerald/Mint  - success, highlights, CTA accents
             Ink     #0F172A Dark Slate    - app icon ground, dark theme ground

   The compiled Tabler stylesheets reference these tokens (see rebrand-css.py),
   so every brand colour on the site resolves through this block. Each
   reference in those files carries a literal fallback, so if this stylesheet
   fails to load the site still renders in-brand rather than colourless.

   All colour pairs below are verified WCAG 2.1 AA by check-contrast.py.
   ========================================================================= */

:root {
  /* --- palette scales --- */
  --at-blue-50: #EBF3FF;
  --at-blue-100: #D6E7FF;
  --at-blue-200: #ADCFFF;
  --at-blue-300: #7DB0FF;
  --at-blue-400: #3D8CFF;
  --at-blue-500: #0066FF;
  --at-blue-600: #0052CC;
  --at-blue-700: #003D99;
  --at-blue-800: #002E73;
  --at-blue-900: #001F4D;

  --at-mint-50: #ECFDF5;
  --at-mint-100: #D1FAE5;
  --at-mint-200: #A7F3D0;
  --at-mint-300: #6EE7B7;
  --at-mint-400: #34D399;
  --at-mint-500: #10B981;
  --at-mint-600: #059669;
  --at-mint-700: #047857;
  --at-mint-800: #065F46;
  --at-mint-900: #064E3B;

  /* --- semantic roles (light theme) --- */
  --at-primary: #0066FF;
  --at-primary-rgb: 0,102,255;
  --at-primary-hover: #0052CC;
  --at-primary-active: #003D99;
  --at-primary-fg: #FFFFFF;
  --at-primary-text: #0066FF;
  --at-primary-soft: #EBF3FF;
  --at-primary-on-soft: #0052CC;
  --at-primary-border: #ADCFFF;
  --at-primary-border-rgb: 173,207,255;
  --at-accent: #10B981;
  --at-accent-rgb: 16,185,129;
  --at-accent-hover: #059669;
  --at-accent-active: #047857;
  --at-accent-fg: #0F172A;
  --at-accent-text: #047857;
  --at-accent-soft: #ECFDF5;
  --at-accent-border: #A7F3D0;
  --at-accent-indicator: #059669;
  --at-accent-on-primary: #6EE7B7;
  --at-ink: #0F172A;
  --at-ink-rgb: 15,23,42;
  --at-surface: #FFFFFF;
  --at-surface-alt: #F1F5F9;
  --at-body-bg: #F8FAFC;
  --at-body-fg: #1E293B;
  --at-muted-fg: #475569;
  --at-accent-600: #059669;
  --at-accent-600-rgb: 5,150,105;

  /* --- focus --- */
  --at-focus-halo: rgba(var(--at-primary-rgb), 0.25);

  /* --- shape --- */
  --at-radius: 0.75rem;
  --at-radius-sm: 0.5rem;
  --at-radius-pill: 999px;
  --at-focus-width: 2px;

  /* --- elevation: blue-tinted rather than neutral grey --- */
  --at-shadow-sm: 0 1px 2px rgba(var(--at-ink-rgb), 0.06),
                  0 1px 3px rgba(var(--at-ink-rgb), 0.08);
  --at-shadow-md: 0 4px 12px rgba(var(--at-primary-rgb), 0.10),
                  0 2px 4px rgba(var(--at-ink-rgb), 0.06);
}

/* --- semantic roles (dark theme) ---
   The scales above are theme-independent; only the roles flip. */
body.theme-dark,
.theme-dark {
  --at-primary: #0066FF;
  --at-primary-rgb: 0,102,255;
  --at-primary-hover: #0052CC;
  --at-primary-active: #003D99;
  --at-primary-fg: #FFFFFF;
  --at-primary-text: #7DB0FF;
  --at-primary-soft: #12244A;
  --at-primary-on-soft: #7DB0FF;
  --at-primary-border: #003D99;
  --at-primary-border-rgb: 0,61,153;
  --at-accent: #34D399;
  --at-accent-rgb: 52,211,153;
  --at-accent-hover: #6EE7B7;
  --at-accent-active: #A7F3D0;
  --at-accent-fg: #0F172A;
  --at-accent-text: #6EE7B7;
  --at-accent-soft: #0B2E24;
  --at-accent-border: #065F46;
  --at-accent-indicator: #34D399;
  --at-accent-on-primary: #6EE7B7;
  --at-ink: #0F172A;
  --at-ink-rgb: 15,23,42;
  --at-surface: #1E293B;
  --at-surface-alt: #1E293B;
  --at-body-bg: #0F172A;
  --at-body-fg: #E2E8F0;
  --at-muted-fg: #94A3B8;
  --at-accent-600: #6EE7B7;
  --at-accent-600-rgb: 110,231,183;

  --at-focus-halo: rgba(var(--at-primary-rgb), 0.40);
  --at-shadow-sm: 0 1px 2px rgba(0, 0, 0, 0.40);
  --at-shadow-md: 0 4px 14px rgba(0, 0, 0, 0.50);
}


/* --- 1. Bind the theme's own semantic variables to the brand tokens --------
   The compiled Tabler build has been retokenised by rebrand-css.py, so these
   are mostly belt-and-braces for rules that read var(--tblr-*) directly. */
:root {
  --tblr-primary:        var(--at-primary);
  --tblr-primary-fg:     var(--at-primary-fg);
  --tblr-blue:           var(--at-primary);
  --tblr-success:        var(--at-accent);
  --tblr-green:          var(--at-accent);
  --tblr-teal:           var(--at-accent-600);
  --tblr-link-color:     var(--at-primary-text);
  --tblr-border-radius:  var(--at-radius);
  /* Tabler's muted grey is 2.7:1 on the dark ground, which fails AA for the
     timestamps and helper text that use it. The token lightens on dark. */
  --tblr-muted:          var(--at-muted-fg);
  --tblr-secondary:      var(--at-muted-fg);
}


/* --- 2. Dark theme ground -------------------------------------------------
   Tabler shipped #1b2434. Moving it to the brand ink (#0F172A) is what makes
   the dark UI, the favicon ground and the app icon read as one thing. */
body.theme-dark,
.theme-dark {
  --tblr-body-bg:        var(--at-body-bg);
  --tblr-body-bg-rgb:    15, 23, 42;
  --tblr-card-bg:        var(--at-surface);
  --tblr-body-color:     var(--at-body-fg);
  background-color:      var(--at-body-bg);
  color:                 var(--at-body-fg);
}


/* --- 3. Focus visibility --------------------------------------------------
   The theme drew focus as a soft box-shadow that several components dropped
   entirely, leaving keyboard users with no visible focus at all. One ring,
   applied once, on real keyboard focus only so it does not fire on mouse
   clicks. Uses two colours so it stays visible on both light and dark grounds
   (WCAG 2.4.11/2.4.13). */
:where(a, button, [role="button"], input, select, textarea, summary,
       .btn, .form-control, .form-select, .form-check-input,
       .page-link, .nav-link, .dropdown-item):focus-visible {
  outline: var(--at-focus-width) solid var(--at-primary);
  outline-offset: 2px;
  box-shadow: 0 0 0 calc(var(--at-focus-width) + 2px) var(--at-focus-halo);
  border-radius: var(--at-radius-sm);
}

/* Never let a component remove the ring it just received. */
:where(.btn, .nav-link, .page-link):focus-visible {
  z-index: 2;   /* keep the ring above adjacent siblings in a group */
}

/* Skip link: present in the DOM but was visually unreachable. */
.at-skip-link {
  position: absolute;
  inset-inline-start: 0.5rem;
  top: -4rem;
  z-index: 2000;
  padding: 0.625rem 1rem;
  background: var(--at-primary);
  color: var(--at-primary-fg);
  border-radius: var(--at-radius-sm);
  font-weight: 600;
  text-decoration: none;
  transition: top 0.15s ease-in-out;
}
.at-skip-link:focus {
  top: 0.5rem;
  color: var(--at-primary-fg);
}


/* --- 4. Accent (mint) as a first-class colour -----------------------------
   Tabler has no "accent" role, so these are new. Fills pair with ink text,
   never white: mint under white text is 2.5:1. */
/* Tabler defines .text-primary / .text-success as rgba(var(--tblr-*-rgb)),
   the same variable .bg-primary / .bg-success fill from. One variable cannot
   be both a fill and a text colour on a dark ground - the fill has to stay
   saturated for white button labels, which leaves the text at 3.0:1. These
   route the text utilities to the -text tokens instead. Identical in light
   mode, correct in dark. */
.text-primary { color: var(--at-primary-text) !important; }
.text-blue    { color: var(--at-primary-text) !important; }
.text-success,
.text-green   { color: var(--at-accent-text) !important; }
.text-teal    { color: var(--at-accent-text) !important; }

/* Outline and ghost buttons draw their label from --tblr-btn-color, which is
   the fill token. Same problem as .text-primary: 3.0:1 on a dark card. */
.btn-outline-primary,
.btn-ghost-primary,
.btn-outline-blue,
.btn-ghost-blue   { color: var(--at-primary-text); }
.btn-outline-success,
.btn-ghost-success,
.btn-outline-green,
.btn-ghost-green,
.btn-outline-teal,
.btn-ghost-teal   { color: var(--at-accent-text); }

/* --- dark-theme legibility carried over from the base theme ---------------
   These are not brand colours, but they are unreadable on the dark ground and
   the brief asks for WCAG compliance across the UI:
     .text-dark          blog post titles, #1e293b on a #1e293b card = 1:1
     .btn-outline-dark   "Continue with GitHub", also 1:1 - invisible
     .btn-outline-secondary/muted  2.7:1 */
body.theme-dark .text-dark { color: var(--at-body-fg) !important; }
body.theme-dark .btn-outline-dark,
body.theme-dark .btn-ghost-dark {
  color: var(--at-body-fg);
  border-color: var(--at-muted-fg);
}
body.theme-dark .btn-outline-dark:hover,
body.theme-dark .btn-ghost-dark:hover {
  color: var(--at-ink);
  background-color: var(--at-body-fg);
}
body.theme-dark .btn-outline-secondary,
body.theme-dark .btn-ghost-secondary,
body.theme-dark .btn-outline-muted,
body.theme-dark .btn-ghost-muted { color: var(--at-muted-fg); }

.text-accent            { color: var(--at-accent-text) !important; }
.bg-accent              { background-color: var(--at-accent) !important;
                          color: var(--at-accent-fg) !important; }
.bg-accent-lt           { background-color: var(--at-accent-soft) !important;
                          color: var(--at-accent-text) !important; }
.border-accent          { border-color: var(--at-accent) !important; }

.btn-accent {
  --tblr-btn-color:            var(--at-accent-fg);
  --tblr-btn-bg:               var(--at-accent);
  --tblr-btn-border-color:     var(--at-accent);
  --tblr-btn-hover-color:      var(--at-accent-fg);
  --tblr-btn-hover-bg:         var(--at-accent-hover);
  --tblr-btn-hover-border-color: var(--at-accent-hover);
  --tblr-btn-active-bg:        var(--at-accent-active);
  --tblr-btn-active-border-color: var(--at-accent-active);
  color: var(--at-accent-fg);
  background-color: var(--at-accent);
  border-color: var(--at-accent);
  font-weight: 600;
}
.btn-accent:hover,
.btn-accent:focus {
  color: var(--at-accent-fg);
  background-color: var(--at-accent-hover);
  border-color: var(--at-accent-hover);
}
.btn-accent:active,
.btn-accent.active {
  color: var(--at-accent-fg);
  background-color: var(--at-accent-active);
  border-color: var(--at-accent-active);
}

/* A mint CTA sitting on a primary-blue band needs the lighter shade: mint on
   blue is 1.9:1. */
.bg-primary .btn-accent,
.at-hero .btn-accent {
  background-color: var(--at-accent-on-primary);
  border-color: var(--at-accent-on-primary);
}

/* Several templates build a header as `{{ $bg }} text-white`, where $bg comes
   from an admin setting. If an admin picks a mint background, that pairing is
   2.5:1 and unreadable. Two classes plus !important outranks .text-white, so
   the label flips to ink no matter what the setting says. */
.bg-accent.text-white,
.bg-success.text-white,
.bg-green.text-white,
.bg-teal.text-white,
.bg-lime.text-white,
.bg-yellow.text-white,
.bg-warning.text-white {
  color: var(--at-accent-fg) !important;
}
.bg-accent.text-white .card-title,
.bg-success.text-white .card-title,
.bg-green.text-white .card-title,
.bg-teal.text-white .card-title,
.bg-lime.text-white .card-title,
.bg-yellow.text-white .card-title,
.bg-warning.text-white .card-title {
  color: inherit;
}

/* Status dot / "Nice" positive indicator. Uses the -600 because a bare mark
   carrying meaning on its own must clear 3:1 against the page. */
.at-status-dot {
  display: inline-block;
  inline-size: 0.5rem;
  block-size: 0.5rem;
  border-radius: 50%;
  background: var(--at-accent-indicator);
  vertical-align: middle;
  margin-inline-end: 0.375rem;
}
.at-badge-nice {
  display: inline-flex;
  align-items: center;
  gap: 0.25rem;
  padding: 0.125rem 0.5rem;
  border-radius: 999px;
  background: var(--at-accent-soft);
  color: var(--at-accent-text);
  border: 1px solid var(--at-accent-border);
  font-size: 0.75rem;
  font-weight: 600;
  line-height: 1.5;
}


/* --- 5. Primary surface polish -------------------------------------------
   Softer radii and a blue-tinted shadow instead of Tabler's neutral grey, so
   cards read as part of the brand rather than as default chrome. */
.card {
  border-radius: var(--at-radius);
  box-shadow: var(--at-shadow-sm);
  transition: box-shadow 0.18s ease, transform 0.18s ease;
}
.card-link:hover,
.card.card-hover:hover {
  box-shadow: var(--at-shadow-md);
  transform: translateY(-2px);
}

.btn {
  border-radius: var(--at-radius-sm);
  font-weight: 500;
  transition: background-color 0.15s ease, border-color 0.15s ease,
              box-shadow 0.15s ease;
}

/* Tinted background utility, now driven by the token rather than a baked
   rgba(). Text steps down one shade to clear AA on the tint. */
.bg-primary-lt {
  background-color: var(--at-primary-soft) !important;
  color: var(--at-primary-on-soft) !important;
}

/* Recessed panels. Templates hard coded #f8f9fa here, which stayed light when
   the dark theme came on and left light-grey text on a light-grey bar. Links
   step down one shade because the brand blue on the -100 grey is 4.4:1. */
.breadcrumb,
.at-panel {
  background: var(--at-surface-alt) !important;
  border-radius: var(--at-radius-sm);
}
.breadcrumb a,
.at-panel a { color: var(--at-primary-on-soft); }
.breadcrumb .breadcrumb-item.active,
.breadcrumb .breadcrumb-item span { color: var(--at-body-fg); }

/* Links: the brand blue is AA on white as-is, so no underline is required for
   contrast, but keep one on hover for 1.4.1 (colour is not the only cue). */
a:not(.btn):not(.nav-link):not(.dropdown-item):not(.page-link) {
  color: var(--at-primary-text);
  text-underline-offset: 0.2em;
}
a:not(.btn):not(.nav-link):not(.dropdown-item):not(.page-link):hover {
  color: var(--at-primary-hover);
  text-decoration: underline;
}


/* --- 6. Responsiveness ----------------------------------------------------
   Touch targets on coarse pointers. WCAG 2.5.8 asks for 24x24 CSS px minimum;
   44px is the comfortable target and costs nothing on desktop because the
   query only fires for touch. */
@media (pointer: coarse) {
  .btn,
  .nav-link,
  .page-link,
  .dropdown-item {
    min-block-size: 2.75rem;
    display: inline-flex;
    align-items: center;
  }
  .dropdown-item,
  .nav-link { inline-size: auto; }
}

/* Wide content must scroll inside itself rather than pushing the page sideways
   on phones. */
@media (max-width: 575.98px) {
  .table-responsive,
  .at-scroll-x { overflow-x: auto; -webkit-overflow-scrolling: touch; }
  .card-body   { padding: 1rem; }
}


/* --- 7. Motion ------------------------------------------------------------
   Honour the OS setting; the theme animates a fair amount by default. */
@media (prefers-reduced-motion: reduce) {
  *,
  *::before,
  *::after {
    animation-duration: 0.001ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.001ms !important;
    scroll-behavior: auto !important;
  }
}


/* --- 8. Forced colours (Windows high contrast) ----------------------------
   Brand colour is dropped by the OS here, so make sure the focus ring and
   button boundaries survive. */
@media (forced-colors: active) {
  :where(a, button, .btn, .form-control, .nav-link):focus-visible {
    outline: 3px solid CanvasText;
    outline-offset: 2px;
  }
  .btn { border: 1px solid ButtonText; }
  .at-status-dot { border: 1px solid CanvasText; }
}
