/* styles.css — kola_dashboard shell.
 *
 * TWO JOBS, and deliberately only two:
 *
 *   1. Declare the design tokens as CSS custom properties, for both
 *      themes. This block is GENERATED from lib/theme.dart — see
 *      tool/gen_theme_css.py. Do not hand-edit it.
 *
 *   2. The handful of genuinely global rules: the viewport-locked
 *      shell, the dot grid, and the desktop/mobile switch.
 *
 * Everything else — spacing, radii, font sizes, per-component colour —
 * stays inline in the Dart components, matching the design export
 * value-for-value. This file does not duplicate those.
 *
 * ── WHAT CHANGED, AND WHY IT MATTERS ─────────────────────────────────
 *
 * The previous version hardcoded #121214 / #F3EEE7 / Inter here, and
 * every component hardcoded dark hex inline. That is precisely why the
 * dashboard had no light mode: adding one meant editing 37 files.
 *
 * Now the values live in custom properties, and components reference
 * them through KolaVar. A theme switch is one attribute on <html>:
 *
 *     document.documentElement.setAttribute('data-theme', 'light');
 *     document.documentElement.removeAttribute('data-theme');  // follow OS
 *
 * Mobile-first, same convention as kola_landing/web/styles.css: the
 * mobile layout is the unqualified default; the desktop layout only
 * turns on above the breakpoint. This is a real, functional media
 * query — not the design tool's Desktop/Mobile preview buttons, which
 * were deliberately not carried into this build (see app.dart).
 */

/* ── BEGIN GENERATED TOKENS — do not edit by hand ──────────────────── */
/* Generated from lib/theme.dart by tool/gen_theme_css.py.
 * Edit the Dart, then re-run the script. Editing this block
 * directly will be overwritten and will make the two disagree
 * in the meantime. */

/* Dark is the default: no attribute set, no OS preference
 * expressed, this is what renders. */
:root {
  /* surfaces */
  --kola-bg: #121214;
  --kola-card: #1B1B1E;
  --kola-border: #2C2A28;
  --kola-pill: #242220;

  /* The Overview glow — a warm wash bleeding down from above the fold.
   * Carried verbatim from Kola Dashboard Shell.dc.html, where it is a
   * THEME TOKEN sitting alongside bg/card/border, not a page style.
   * Dark carries more alpha (0.10) than light (0.06) because the same
   * warmth reads far weaker against a near-black background. */
  --kola-glow: radial-gradient(ellipse 900px 500px at 50% -10%, rgba(193,85,46,0.10), transparent 70%);


  /* text */
  --kola-text: #F3EEE7;
  --kola-muted-strong: #B9B3AC;
  --kola-muted: #9C9691;

  /* brand */
  --kola-accent: #C1552E;
  --kola-accent-fill: #9C4520;
  --kola-accent-text: #FFF6EE;

  /* semantic */
  --kola-success: #34A37E;
  --kola-danger: #E5484D;
  --kola-warning: #E2A33D;

  /* semantic surfaces */
  --kola-success-bg: #12261F;
  --kola-danger-bg: #2A1414;
  --kola-warning-bg: #241F14;
  --kola-info-bg: #1B2430;
  --kola-info-text: #7CB0E9;
  --kola-success-bright: #7ED8B0;

  /* category tints */
  --kola-tint-0-surface: #241A14;
  --kola-tint-0-icon: #3A2A1E;
  --kola-tint-1-surface: #12261F;
  --kola-tint-1-icon: #1F3B30;
  --kola-tint-2-surface: #1B2430;
  --kola-tint-2-icon: #28374A;
  --kola-tint-3-surface: #241F14;
  --kola-tint-3-icon: #3A331F;

  /* typefaces */
  --kola-font-display: 'Space Grotesk', sans-serif;
  --kola-font-sans: 'Plus Jakarta Sans', sans-serif;
  --kola-font-mono: 'IBM Plex Mono', monospace;

  /* motion — theme-independent, so declared once here rather
   * than repeated in the light block */
  --kola-motion-instant: 80ms;
  --kola-motion-fast: 140ms;
  --kola-motion-base: 200ms;
  --kola-motion-slow: 320ms;
  --kola-ease: cubic-bezier(0.2, 0, 0, 1);
  --kola-ease-out: cubic-bezier(0, 0, 0.2, 1);
}

/* An explicit choice, set on <html>. This is currently the ONLY
 * way to get light mode — the OS-driven path below is disabled. */
:root[data-theme='light'] {
  /* surfaces */
  --kola-bg: #FAF6EF;
  --kola-card: #FFFFFF;
  --kola-border: #E8E1D6;
  --kola-pill: #F1EAE0;

  /* Same wash, lower alpha — see the dark block. */
  --kola-glow: radial-gradient(ellipse 900px 500px at 50% -10%, rgba(193,85,46,0.06), transparent 70%);


  /* text */
  --kola-text: #1C1815;
  --kola-muted-strong: #5B554F;
  --kola-muted: #7A736C;

  /* brand */
  --kola-accent: #C1552E;
  --kola-accent-fill: #9C4520;
  --kola-accent-text: #FFF6EE;

  /* semantic */
  --kola-success: #227A5B;
  --kola-danger: #C4373D;
  --kola-warning: #9C6A14;

  /* semantic surfaces */
  --kola-success-bg: #EAF6F0;
  --kola-danger-bg: #FBEAEA;
  --kola-warning-bg: #FBF3E6;
  --kola-info-bg: #EAF1FB;
  --kola-info-text: #2C6FB5;
  --kola-success-bright: #227A5B;

  /* category tints */
  --kola-tint-0-surface: #FBEFE6;
  --kola-tint-0-icon: #F3D9C4;
  --kola-tint-1-surface: #EAF6F0;
  --kola-tint-1-icon: #CFEEE0;
  --kola-tint-2-surface: #EAF1FB;
  --kola-tint-2-icon: #CFE0F3;
  --kola-tint-3-surface: #FBF3E6;
  --kola-tint-3-icon: #F3E3BE;
}

/* OS-FOLLOWING IS DISABLED. Not an oversight — see FOLLOW_SYSTEM
 * in tool/gen_theme_css.py. In short: 37 components still paint
 * dark hex literals that cannot respond to a theme change, so
 * honouring the OS here would hand every light-mode user a light
 * page full of dark-on-dark components, without their asking.
 *
 * Set FOLLOW_SYSTEM = True and re-run this script once
 * `grep -rn KolaDashboard lib/` comes back empty. */

/*
/* No explicit choice: follow the operating system. Scoped to
 * :not([data-theme]) so a user who HAS chosen keeps their choice
 * when their phone flips to night mode at sunset. * /
@media (prefers-color-scheme: light) {
  :root:not([data-theme]) {
    /* surfaces * /
    --kola-bg: #FAF6EF;
    --kola-card: #FFFFFF;
    --kola-border: #E8E1D6;
    --kola-pill: #F1EAE0;

    /* text * /
    --kola-text: #1C1815;
    --kola-muted-strong: #5B554F;
    --kola-muted: #7A736C;

    /* brand * /
    --kola-accent: #C1552E;
    --kola-accent-fill: #9C4520;
    --kola-accent-text: #FFF6EE;

    /* semantic * /
    --kola-success: #227A5B;
    --kola-danger: #C4373D;
    --kola-warning: #9C6A14;

    /* semantic surfaces * /
    --kola-success-bg: #EAF6F0;
    --kola-danger-bg: #FBEAEA;
    --kola-warning-bg: #FBF3E6;
    --kola-info-bg: #EAF1FB;
    --kola-info-text: #2C6FB5;
    --kola-success-bright: #227A5B;

    /* category tints * /
    --kola-tint-0-surface: #FBEFE6;
    --kola-tint-0-icon: #F3D9C4;
    --kola-tint-1-surface: #EAF6F0;
    --kola-tint-1-icon: #CFEEE0;
    --kola-tint-2-surface: #EAF1FB;
    --kola-tint-2-icon: #CFE0F3;
    --kola-tint-3-surface: #FBF3E6;
    --kola-tint-3-icon: #F3E3BE;
  }
}
*/
/* ── END GENERATED TOKENS ──────────────────────────────────────────── */

* {
  box-sizing: border-box;
}

/* Viewport-locked shell: the browser window itself never scrolls.
 * Every page's own root element is height:100vh with its own
 * overflow-y:auto (or a specific flex:1 child region is, for pages
 * with fixed chrome like a header/sidebar) — scrolling always happens
 * inside a page's own container, never at the document/body level.
 * See kola_dashboard's pages/* for where each page's scroll region is. */
html, body {
  margin: 0;
  padding: 0;
  height: 100%;
  overflow: hidden;
  background: var(--kola-bg);
  color: var(--kola-text);
  font-family: var(--kola-font-sans);
}

/* Tells the browser to render native UI — scrollbars, form controls,
 * the on-screen keyboard — to match. Without this a light-themed page
 * still gets dark scrollbars, which reads as a rendering bug. */
:root {
  color-scheme: dark;
}

:root[data-theme='light'] {
  color-scheme: light;
}

/* No `prefers-color-scheme` rule here, deliberately. It would have to
 * agree with the generated token block, and that block does not follow
 * the OS yet — see FOLLOW_SYSTEM in tool/gen_theme_css.py. A
 * color-scheme that disagrees with the tokens gives light scrollbars on
 * a dark page, which looks like a rendering fault rather than a
 * setting. These two turn on together or not at all. */

/* The dot grid.
 *
 * HAND-WRITTEN, not generated: it is an alpha over the background
 * rather than a token, and it is the one value that cannot simply be
 * inverted — the same white dots that read as texture on #121214 are
 * invisible on #FAF6EF. Light mode gets dark dots at a lower alpha,
 * because dark-on-light reads considerably heavier than light-on-dark
 * at the same opacity. */
body {
  background-image: radial-gradient(circle, rgba(255, 255, 255, 0.06) 1.4px, transparent 1.4px);
  background-size: 24px 24px;
}

:root[data-theme='light'] body {
  background-image: radial-gradient(circle, rgba(28, 24, 21, 0.045) 1.4px, transparent 1.4px);
}

/* Again no `prefers-color-scheme` rule, for the same reason as
 * color-scheme above: it turns on with the token block, not before. */

a {
  text-decoration: none;
}

textarea {
  font-family: inherit;
}

/* Money and IDs. Tabular figures stop digits shifting between rows,
 * which is the difference between a column of prices you can scan and
 * one you have to read. */
.kola-num {
  font-family: var(--kola-font-mono);
  font-variant-numeric: tabular-nums;
}

/* Honour a system-level request for less motion. KolaMotion's durations
 * are short, but "short" is not "none" for someone with a vestibular
 * disorder. */
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
    scroll-behavior: auto !important;
  }
}

/* ── The NEW shell's responsive switch ────────────────────────────────
 *
 * 1024px — KolaBreak.desktop. Below it the app wears mobile chrome (top
 * bar + bottom tab bar); at and above it, the 248px sidebar.
 *
 * SEPARATE CLASSES FROM `.kola-dash-*` BELOW, on purpose. The old
 * classes switch at 960 and are still used by every screen not yet
 * migrated. Changing that number would silently reflow 37 screens in
 * the 960–1024 band as a side effect of building something else. The
 * old pair gets deleted with the last old screen, not before.
 *
 * There is no separate tablet layout, matching the design export, which
 * defines exactly two. The mobile layout is fluid rather than the
 * export's fixed 390px frame, so a tablet at 800px gets a comfortable
 * wide version of it rather than a phone mockup floating in a gutter. */

.kola-shell-mobile {
  display: flex;
}

.kola-shell-desktop {
  display: none;
}

@media (min-width: 1024px) {
  .kola-shell-mobile {
    display: none;
  }

  .kola-shell-desktop {
    display: flex;
  }
}

/* Interaction states.
 *
 * These cannot be inline styles — there is no inline `:hover`. Keeping
 * them here rather than inventing a per-component <style> means every
 * interactive surface in the shell reacts the same way, which is the
 * thing users actually notice when it is inconsistent. */

.kola-nav-row {
  transition: background var(--kola-motion-fast) var(--kola-ease),
              color var(--kola-motion-fast) var(--kola-ease);
}

.kola-nav-row:hover {
  background: var(--kola-pill);
  color: var(--kola-text);
}

.kola-pressable {
  transition: opacity 140ms ease, background 140ms ease;
  cursor: pointer;
}

.kola-pressable:hover {
  opacity: 0.88;
}

/* Keyboard focus must stay visible. `:focus-visible` rather than
 * `:focus` so a mouse click does not leave a ring behind, but tabbing
 * always does — removing the outline outright is the single most common
 * way a dashboard becomes unusable without a mouse. */
.kola-nav-row:focus-visible,
.kola-pressable:focus-visible,
a:focus-visible,
button:focus-visible,
input:focus-visible {
  outline: 2px solid var(--kola-accent);
  outline-offset: 2px;
  border-radius: 8px;
}

/* Touch targets. 44px is the floor for anything a thumb has to hit on
 * the bottom bar — below that, miss rates climb sharply on the 360px
 * phones this product is built for. */
.kola-tab {
  min-height: 44px;
}

/* Loading skeletons.
 *
 * A shimmer rather than a spinner, and shaped like the content it
 * replaces. On a slow connection — which is the normal case here, not
 * the edge case — a spinner tells you nothing is ready; a skeleton in
 * the right shape tells you what is coming and stops the page jumping
 * when it lands.
 *
 * The gradient is built from theme variables, so it inverts correctly
 * in light mode instead of flashing a dark band across a pale card. */
@keyframes kola-shimmer {
  0% { background-position: -300px 0; }
  100% { background-position: 300px 0; }
}

.kola-skel {
  background-color: var(--kola-card);
  background-image: linear-gradient(
    90deg,
    var(--kola-card) 0px,
    var(--kola-pill) 80px,
    var(--kola-card) 160px
  );
  background-size: 600px 100%;
  animation: kola-shimmer 1.3s ease-in-out infinite;
}

/* ── Splash ───────────────────────────────────────────────────────────
 *
 * Carried over from `Kola Splash.dc.html` keyframe-for-keyframe. The
 * timings are the design's, not approximations: the leaf draws itself,
 * fills, settles with a slight overshoot, then the wordmark arrives one
 * letter at a time, a rule grows under it and the tagline fades in.
 *
 * THE ONE THING THAT CHANGED IS WHEN IT LEAVES. The export dismisses on
 * a fixed 2.3s timer because a design tool has nothing to wait for.
 * Here it waits for the real session restore and workspace fetch, with
 * a floor so it cannot flash and vanish. See splash_screen.dart.
 *
 * Colours use theme variables rather than the export's hardcoded hex,
 * so the splash does not stay black once light mode is on. */

@keyframes kola-bg-in      { to { opacity: 1; } }
@keyframes kola-fill-in    { to { opacity: 1; } }
@keyframes kola-draw       { to { stroke-dashoffset: 0; } }
@keyframes kola-ring-expand{ 0% { opacity: 0.9; transform: scale(0.4); }
                           100% { opacity: 0;   transform: scale(1); } }
@keyframes kola-mark-settle{ 0% { transform: scale(0.92); }
                            60% { transform: scale(1.04); }
                           100% { transform: scale(1); } }
@keyframes kola-glow-pulse { 0%, 100% { opacity: 0.35; transform: scale(1); }
                                   50% { opacity: 0.6;  transform: scale(1.15); } }
@keyframes kola-letter-in  { from { opacity: 0; transform: translateY(10px); }
                               to { opacity: 1; transform: translateY(0); } }
@keyframes kola-rule-grow  { from { width: 0; } to { width: 34px; } }
@keyframes kola-word-in    { from { opacity: 0; transform: translateY(6px); }
                               to { opacity: 1; transform: translateY(0); } }
@keyframes kola-splash-dot { 0%, 100% { opacity: 0.25; transform: scale(0.85); }
                                   50% { opacity: 1;    transform: scale(1.15); } }
@keyframes kola-fade-out   { to { opacity: 0; transform: scale(0.98); } }

.kola-splash-bg   { opacity: 0; animation: kola-bg-in 900ms ease-out forwards; }
.kola-ring        { animation: kola-ring-expand 1600ms ease-out infinite; }
.kola-glow        { animation: kola-glow-pulse 2.4s ease-in-out infinite; }
.kola-mark-wrap   { animation: kola-mark-settle 900ms cubic-bezier(.22,1,.36,1) 650ms both; }
.kola-leaf-outline{ stroke-dasharray: 92; stroke-dashoffset: 92;
                    animation: kola-draw 850ms ease-out 150ms forwards; }
.kola-leaf-fill   { opacity: 0; animation: kola-fill-in 450ms ease-out 750ms forwards; }
.kola-letter      { display: inline-block; opacity: 0;
                    animation: kola-letter-in 480ms cubic-bezier(.22,1,.36,1) forwards; }
.kola-rule        { display: block; height: 1.5px; background: var(--kola-accent);
                    width: 0; margin: 10px auto 0;
                    animation: kola-rule-grow 500ms ease-out 1500ms forwards; }
.kola-tag         { opacity: 0; animation: kola-word-in 500ms ease-out 1650ms forwards; }
.kola-splash-dot  { animation: kola-splash-dot 1.1s ease-in-out infinite; }
.kola-splash-leaving { animation: kola-fade-out 500ms cubic-bezier(.4,0,1,1) forwards; }

/* Reduced motion: the whole sequence collapses to a static, finished
 * frame. The universal rule above already zeroes the durations, which
 * would otherwise freeze the leaf mid-draw and leave the wordmark
 * invisible — every element here starts at opacity 0 and is animated
 * INTO view, so killing the animation without this would show an empty
 * screen. This is the finished state, shown immediately. */
@media (prefers-reduced-motion: reduce) {
  .kola-splash-bg,
  .kola-leaf-fill,
  .kola-letter,
  .kola-tag {
    opacity: 1 !important;
  }

  .kola-leaf-outline {
    stroke-dashoffset: 0 !important;
  }

  .kola-rule {
    width: 34px !important;
  }

  .kola-ring,
  .kola-glow,
  .kola-splash-dot {
    display: none;
  }
}

/* Under reduced motion the universal rule above already forces
 * animation-duration to 0.01ms, so the shimmer stops dead mid-gradient
 * and leaves a lopsided bright band frozen across the block. Removing
 * the gradient gives a clean, static placeholder instead.
 *
 * No replacement animation is attempted: that universal `!important`
 * duration would override any timing set here, so a pulse would look
 * like it was set up and then broken. A static skeleton still does the
 * job — it holds the shape, which is most of the point. */
@media (prefers-reduced-motion: reduce) {
  .kola-skel {
    background-image: none;
  }
}

/* ── The OLD shell's desktop / mobile switch ──────────────────────────
 *
 * Still 960px. Used only by screens on the previous design. Delete this
 * block together with the last of them. */

.kola-dash-mobile {
  display: flex;
}

.kola-dash-desktop {
  display: none;
}

@media (min-width: 960px) {
  .kola-dash-mobile {
    display: none;
  }

  .kola-dash-desktop {
    display: flex;
  }
}

/* ── Product detail: photos beside the facts ──────────────────────────
 *
 * The seller view used to stack the photo above the title, which put the
 * name, price, margin and stock below the fold on a laptop — you opened
 * a product and then had to scroll UP to read it. The design has two
 * columns starting at the same top edge.
 *
 * A CONTAINER query, not a media query. This page renders inside the
 * dashboard shell beside a fixed sidebar, so the viewport is wide long
 * before this column is; a `min-width: 860px` media query would hold two
 * columns in a space that only fits one. Container queries ask the
 * question that actually matters — how much room does THIS have.
 *
 * TWO elements, deliberately. A container query cannot style its own
 * container: `container-type` on the grid itself would make the grid a
 * container for its CHILDREN and the @container rule below would never
 * match it. So the outer div declares the container and the inner div is
 * the grid that responds to it.
 *
 * 340px for the photo rather than a fraction: a product photo has a job
 * to do at a known size, and letting it grow with the window only steals
 * width from the text, which is the column that benefits from it. */

.kola-detail-split {
  container-type: inline-size;
}

.kola-detail-split > .kola-detail-grid {
  display: grid;
  gap: 24px;
  grid-template-columns: minmax(0, 1fr);
}

@container (min-width: 700px) {
  .kola-detail-split > .kola-detail-grid {
    grid-template-columns: 340px minmax(0, 1fr);
    align-items: start;
  }
}
