/* ============================================================
   @mianda/ds — v1
   the shared design language for mianda.dev and every {app}.mianda.dev

   https://ds.mianda.dev/v1/ds.css

   This file is the single source of truth for tokens and .dv-* components.
   Do not copy it into an app — link it, or import '@mianda/ds/ds.css'.
   ============================================================ */

@import url('https://fonts.googleapis.com/css2?family=Space+Grotesk:wght@400;500;600;700&family=JetBrains+Mono:ital,wght@0,400;0,500;0,700;1,400&display=swap');

/* ---------- tokens: typography ---------- */
:root{
  --font-sans:'Space Grotesk',system-ui,sans-serif;
  --font-mono:'JetBrains Mono',ui-monospace,'SF Mono',monospace;
  --fs-display:clamp(44px,6vw,76px);
  --fs-h1:32px; --fs-h2:22px; --fs-body:14px; --fs-small:12px; --fs-label:11px;
  --ls-label:.08em;
}

/* ---------- tokens: color ---------- */
:root{
  /* base */
  --white:#fcfcfc; --black:#0b0b0b;
  --green:oklch(0.88 0.24 136);
  --green-deep:oklch(0.55 0.15 140);
  --green-glow:oklch(0.88 0.24 136 / .28);
  /* semantic — light */
  --bg:#fafafa;
  --surface-1:#f1f1f1; --surface-2:#e8e8e8; --surface-3:#dedede;
  --text:#141414; --text-2:#5f5f5f; --text-3:#9b9b9b;
  --border:rgba(0,0,0,.10); --border-strong:rgba(0,0,0,.24);
  --accent:var(--green); --on-accent:#0c1207;
  --accent-text:var(--green-deep); --accent-glow:var(--green-glow);
  --hover:rgba(0,0,0,.05); --press:rgba(0,0,0,.10);
  --glass:rgba(250,250,250,.78);
  --shadow-1:0 1px 2px rgba(0,0,0,.06);
  --shadow-2:0 10px 30px rgba(0,0,0,.14);
  color-scheme:light;
}
[data-theme="dark"]{
  --bg:#0b0b0b;
  --surface-1:#151515; --surface-2:#1e1e1e; --surface-3:#282828;
  --text:#f1f1f1; --text-2:#a3a3a3; --text-3:#6a6a6a;
  --border:rgba(255,255,255,.12); --border-strong:rgba(255,255,255,.3);
  --accent-text:var(--green);
  --hover:rgba(255,255,255,.06); --press:rgba(255,255,255,.12);
  --glass:rgba(11,11,11,.72);
  --shadow-1:0 1px 2px rgba(0,0,0,.5);
  --shadow-2:0 10px 30px rgba(0,0,0,.55);
  color-scheme:dark;
}

/* ---------- tokens: shape ---------- */
:root{
  --r-xs:6px; --r-sm:10px; --r-md:16px; --r-lg:24px; --r-full:999px;
  /* material-you asymmetric "cookie" radius */
  --r-asym:23px 23px 23px 6px;
  /* brand mark — the aperture: outer sharp corner bottom-left, inner sharp top-right.
     same corner signature as --r-asym, so the mark and the UI share one shape language */
  --r-mark:30% 30% 30% 7%; --r-mark-inner:30% 7% 30% 30%; --mark-inset:26%;
  --mark-size:16px; --mark-size-sm:13px; --mark-size-lg:112px;
  --sp-1:4px; --sp-2:8px; --sp-3:12px; --sp-4:16px; --sp-5:24px; --sp-6:32px; --sp-7:48px; --sp-8:64px;
  --h-control:40px; --h-input:44px; --h-bar:46px;
}

/* ---------- base ---------- */
*,*::before,*::after{box-sizing:border-box}
body{margin:0;background:var(--bg);color:var(--text);font-family:var(--font-sans);font-size:var(--fs-body);-webkit-font-smoothing:antialiased;text-rendering:optimizeLegibility}
a{color:var(--text);text-decoration:underline;text-decoration-color:var(--accent);text-decoration-thickness:1.5px;text-underline-offset:3px}
a:hover{color:var(--accent-text)}
::selection{background:var(--accent);color:var(--on-accent)}
h1,h2,h3,p{margin:0}
.dv-mono{font-family:var(--font-mono)}
.dv-label{font-family:var(--font-mono);font-size:var(--fs-label);letter-spacing:var(--ls-label);text-transform:uppercase;color:var(--text-2)}
.dv-placeholder{background:repeating-linear-gradient(45deg,var(--surface-2) 0 10px,var(--surface-1) 10px 20px);border:1px solid var(--border);border-radius:var(--r-md);display:flex;align-items:center;justify-content:center;color:var(--text-3);font-family:var(--font-mono);font-size:12px}
.dv-skip{position:absolute;left:-9999px}
.dv-skip:focus{left:14px;top:14px;z-index:60;padding:8px 14px;border-radius:var(--r-full);background:var(--accent);color:var(--on-accent);text-decoration:none}

/* ---------- buttons ---------- */
/* also used on <a> — kill the inherited link underline */
.dv-btn{position:relative;display:inline-flex;align-items:center;justify-content:center;gap:8px;font-family:var(--font-sans);font-weight:500;border:1px solid transparent;border-radius:var(--r-full);cursor:pointer;white-space:nowrap;overflow:hidden;text-decoration:none;transition:background .15s,color .15s,border-color .15s}
.dv-btn::after{content:"";position:absolute;inset:0;background:currentColor;opacity:0;transition:opacity .12s;pointer-events:none}
.dv-btn:hover::after{opacity:.08}
.dv-btn:active::after{opacity:.15}
.dv-btn:focus-visible{outline:2px solid var(--accent);outline-offset:2px}
.dv-btn:disabled,.dv-btn[aria-disabled="true"]{opacity:.35;pointer-events:none}
.dv-btn--sm{height:32px;padding:0 14px;font-size:13px}
.dv-btn--md{height:40px;padding:0 20px;font-size:14px}
.dv-btn--lg{height:48px;padding:0 26px;font-size:15px}
.dv-btn--primary{background:var(--accent);color:var(--on-accent)}
.dv-btn--tonal{background:var(--surface-2);color:var(--text)}
.dv-btn--outline{background:transparent;border-color:var(--border-strong);color:var(--text)}
.dv-btn--ghost{background:transparent;color:var(--text-2)}
.dv-btn--inverse{background:var(--text);color:var(--bg)}
.dv-iconbtn{width:40px;padding:0;flex:0 0 auto}
.dv-iconbtn.dv-btn--sm{width:32px}
.dv-iconbtn.dv-btn--lg{width:48px}
/* currentColor with a gap at the top, so one spinner reads on every variant */
.dv-btn__spinner{width:15px;height:15px;flex:0 0 auto;border-radius:50%;opacity:.65;
  border:2px solid currentColor;border-top-color:transparent;animation:dvSpin .8s linear infinite}
@keyframes dvSpin{to{transform:rotate(360deg)}}

/* ---------- chip ---------- */
/* a selectable filter token: denser than a button, interactive unlike a tag */
.dv-chip{display:inline-flex;align-items:center;gap:8px;height:28px;padding:0 12px;border-radius:var(--r-xs);border:1px solid var(--border);background:transparent;color:var(--text-2);font-family:var(--font-mono);font-size:11.5px;cursor:pointer;white-space:nowrap;transition:background .15s,color .15s,border-color .15s}
.dv-chip:hover{color:var(--text);border-color:var(--border-strong)}
.dv-chip--selected{background:var(--text);color:var(--bg);border-color:transparent}
.dv-chip:focus-visible{outline:2px solid var(--accent);outline-offset:2px}
.dv-chip:disabled{opacity:.35;pointer-events:none}

/* ---------- fields ---------- */
.dv-field{display:flex;flex-direction:column;gap:6px;font-family:var(--font-sans)}
.dv-field__label{font-family:var(--font-mono);font-size:var(--fs-label);letter-spacing:var(--ls-label);text-transform:uppercase;color:var(--text-2)}
.dv-input{height:var(--h-input);padding:0 14px;border-radius:var(--r-sm);background:var(--surface-1);border:1px solid var(--border);color:var(--text);font-family:var(--font-sans);font-size:14px;width:100%;transition:border-color .15s,box-shadow .15s}
.dv-input::placeholder{color:var(--text-3)}
.dv-input:focus{outline:none;border-color:var(--accent);box-shadow:0 0 0 3px var(--accent-glow)}
textarea.dv-input{height:auto;padding:12px 14px;resize:vertical}
.dv-field__hint{font-family:var(--font-mono);font-size:11px;color:var(--text-3)}

/* ---------- slider ---------- */
/* the filled portion is driven by --fill, which <dv-slider> keeps in sync —
   webkit has no ::-moz-range-progress equivalent, hence the gradient */
.dv-slider{-webkit-appearance:none;appearance:none;width:100%;height:20px;background:transparent;cursor:pointer;margin:0}
.dv-slider::-webkit-slider-runnable-track{height:4px;border-radius:999px;background:linear-gradient(to right,var(--accent) 0 var(--fill,50%),var(--surface-3) var(--fill,50%) 100%)}
.dv-slider::-webkit-slider-thumb{-webkit-appearance:none;width:16px;height:16px;border-radius:999px;background:var(--bg);border:1.5px solid var(--text);margin-top:-6px;transition:transform .12s}
.dv-slider:hover::-webkit-slider-thumb{transform:scale(1.15)}
.dv-slider::-moz-range-track{height:4px;border-radius:999px;background:var(--surface-3)}
.dv-slider::-moz-range-progress{height:4px;border-radius:999px;background:var(--accent)}
.dv-slider::-moz-range-thumb{width:14px;height:14px;border-radius:999px;background:var(--bg);border:1.5px solid var(--text)}
.dv-slider:focus-visible{outline:2px solid var(--accent);outline-offset:2px;border-radius:999px}
.dv-slider__head{display:flex;align-items:baseline;justify-content:space-between;gap:12px}
.dv-slider__val{font-family:var(--font-mono);font-size:12px;color:var(--text)}

/* ---------- switch ---------- */
.dv-switch{display:inline-flex;align-items:center;gap:10px;cursor:pointer;font-size:14px;color:var(--text);position:relative}
.dv-switch input{position:absolute;opacity:0;width:0;height:0}
.dv-switch__track{width:46px;height:26px;border-radius:999px;background:var(--surface-3);border:1px solid var(--border);position:relative;transition:background .18s,border-color .18s;flex:0 0 auto}
.dv-switch__thumb{position:absolute;top:3px;left:3px;width:18px;height:18px;border-radius:999px;background:var(--bg);border:1px solid var(--border);transition:transform .18s,background .18s}
.dv-switch input:checked + .dv-switch__track{background:var(--accent);border-color:transparent}
.dv-switch input:checked + .dv-switch__track .dv-switch__thumb{transform:translateX(20px);background:var(--on-accent);border-color:transparent}
.dv-switch input:focus-visible + .dv-switch__track{outline:2px solid var(--accent);outline-offset:2px}

/* ---------- card ---------- */
/* a card is a non-bg surface, so it declares its own mark field — otherwise
   every author has to remember, and the aperture punches the wrong colour */
.dv-card{background:var(--surface-1);--mark-field:var(--surface-1);border:1px solid var(--border);border-radius:var(--r-lg);padding:22px;color:var(--text)}
.dv-card--interactive{cursor:pointer;transition:border-color .15s,background .15s,transform .15s;text-decoration:none}
.dv-card--interactive:hover{border-color:var(--border-strong);background:var(--surface-2)}
.dv-card--interactive:active{transform:scale(.99)}
.dv-card--interactive:focus-visible{outline:2px solid var(--accent);outline-offset:2px}

/* ---------- badge + tag ---------- */
.dv-badge{display:inline-flex;align-items:center;gap:6px;height:22px;padding:0 10px;border-radius:999px;font-family:var(--font-mono);font-size:10.5px;letter-spacing:.08em;text-transform:uppercase}
.dv-badge--neutral{background:var(--surface-2);color:var(--text-2)}
.dv-badge--accent{background:var(--accent);color:var(--on-accent)}
.dv-badge--outline{border:1px solid var(--border-strong);color:var(--text-2);background:transparent}
.dv-badge__dot{width:6px;height:6px;border-radius:2px;background:var(--accent);flex:0 0 auto}
.dv-tag{display:inline-flex;align-items:center;height:26px;padding:0 10px;border-radius:var(--r-xs);background:var(--surface-2);color:var(--text-2);font-family:var(--font-mono);font-size:12px}

/* ---------- tabs ---------- */
.dv-tabs{display:inline-flex;padding:4px;gap:2px;background:var(--surface-1);border:1px solid var(--border);border-radius:999px}
.dv-tab{height:32px;padding:0 16px;border:none;border-radius:999px;background:transparent;color:var(--text-2);font-family:var(--font-mono);font-size:12px;letter-spacing:.04em;cursor:pointer;transition:background .15s,color .15s}
.dv-tab:hover{color:var(--text)}
.dv-tab--active{background:var(--text);color:var(--bg)}
.dv-tab:focus-visible{outline:2px solid var(--accent);outline-offset:2px}

/* ---------- header ---------- */
/* `.dv-header` is applied to the <dev-header> custom element itself, so the
   sticky box is the host — no wrapper element in between. */
.dv-header{position:sticky;top:0;z-index:50;display:flex;align-items:flex-start;justify-content:space-between;gap:12px;padding:14px clamp(16px,3vw,28px)}
.dv-header__pill{display:flex;align-items:center;gap:4px;height:var(--h-bar);padding:0 8px;background:var(--glass);backdrop-filter:blur(14px);-webkit-backdrop-filter:blur(14px);border:1px solid var(--border);border-radius:999px;position:relative}
.dv-header--asym .dv-header__pill:first-child{border-radius:23px 23px 23px 6px}
.dv-header--asym .dv-header__pill:last-child{border-radius:23px 23px 6px 23px}
.dv-header--angle .dv-header__pill{border-radius:0;border:none;background:var(--surface-2)}
.dv-header--angle .dv-header__pill:first-child{clip-path:polygon(0 0,100% 0,calc(100% - 16px) 100%,0 100%);padding-right:26px}
.dv-header--angle .dv-header__pill:last-child{clip-path:polygon(16px 0,100% 0,100% 100%,0 100%);padding-left:26px}
.dv-header__mark{display:flex;align-items:center;gap:9px;padding:0 12px;text-decoration:none;color:var(--text)}
.dv-header__mark:hover{color:var(--text)}
.dv-header__mark strong{font-weight:600;font-size:15px;letter-spacing:-.01em}
.dv-header__name{display:flex;align-items:baseline}
/* home — a 32px surface circle holding ⌂, next to the wordmark.
   absent on the hub itself, which is where it would point. */
.dv-header__home{width:32px;height:32px;flex:0 0 auto;display:inline-flex;align-items:center;justify-content:center;margin-right:4px;border-radius:999px;border:none;background:var(--surface-2);color:var(--text-2);font-size:14px;line-height:1;cursor:pointer;text-decoration:none;transition:background 150ms ease,color 150ms ease}
.dv-header__home:hover{background:var(--surface-3);color:var(--text)}
.dv-header__home:active{transform:scale(.96)}
.dv-mark-dev{font-family:var(--font-mono);font-size:11px;color:var(--text-3);letter-spacing:.06em}

/* ---------- the mark: "aperture" ----------
   A green square with a square knocked out of it, the two sharp corners
   diagonally opposing — outer bottom-left, inner top-right. It reads as a lens
   or a viewport: a thing you look through.

   The knockout is a REAL hole. It paints --mark-field, which defaults to --bg;
   set --mark-field on the parent whenever the mark sits on another surface,
   or the hole will show the wrong colour.

   Never below 13px (the aperture closes up), never recoloured, never outlined,
   never rotated, never set inside another container shape. On green, invert. */
.dv-mark,.dv-mark-dot{position:relative;display:inline-block;width:var(--mark-size);height:var(--mark-size);background:var(--accent);border-radius:var(--r-mark);flex:0 0 auto}
.dv-mark::after,.dv-mark-dot::after{content:"";position:absolute;inset:var(--mark-inset);background:var(--mark-field,var(--bg));border-radius:var(--r-mark-inner)}
.dv-mark--sm{width:var(--mark-size-sm);height:var(--mark-size-sm)}
.dv-mark--lg{width:var(--mark-size-lg);height:var(--mark-size-lg)}
/* on an accent field the mark inverts: dark body, green hole */
.dv-mark--invert{background:var(--on-accent)}
.dv-mark--invert::after{background:var(--accent)}
.dv-glyph-grid{display:grid;grid-template-columns:repeat(2,3px);gap:3px}
.dv-glyph-grid i{width:3px;height:3px;background:currentColor;border-radius:1px}
.dv-switcher{position:absolute;top:calc(100% + 8px);right:0;min-width:250px;background:var(--bg);border:1px solid var(--border);border-radius:var(--r-md);padding:6px;box-shadow:var(--shadow-2);display:flex;flex-direction:column;gap:2px}
.dv-switcher a{display:flex;align-items:center;gap:10px;padding:10px 12px;border-radius:var(--r-sm);text-decoration:none;color:var(--text);font-size:14px}
.dv-switcher a:hover{background:var(--hover);color:var(--text)}
.dv-switcher__idx{font-family:var(--font-mono);font-size:10px;color:var(--text-3);width:24px;flex:0 0 auto}
.dv-switcher__cur{width:7px;height:7px;border-radius:2px;background:var(--accent);margin-left:auto}

/* ---------- footer ---------- */
.dv-footer{display:flex;align-items:center;justify-content:space-between;gap:16px;padding:18px clamp(16px,3vw,28px);border-top:1px solid var(--border);font-family:var(--font-mono);font-size:11px;color:var(--text-3);letter-spacing:.03em}
.dv-footer a{color:var(--text-3);text-decoration:none}
.dv-footer a:hover{color:var(--text)}
.dv-footer__dot{position:relative;width:var(--mark-size-sm);height:var(--mark-size-sm);border-radius:var(--r-mark);background:var(--accent);display:inline-block;margin-right:9px;vertical-align:-2px;flex:0 0 auto}
.dv-footer__dot::after{content:"";position:absolute;inset:var(--mark-inset);background:var(--mark-field,var(--bg));border-radius:var(--r-mark-inner)}
.dv-footer__links{display:flex;gap:16px}

/* ---------- cfg + solid bars ---------- */
.dv-cfg{font-family:var(--font-mono);font-size:11px;letter-spacing:.05em}
[data-bars="solid"] .dv-header__pill{background:var(--bg);backdrop-filter:none;-webkit-backdrop-filter:none;box-shadow:var(--shadow-1)}
[data-bars="solid"] .dv-footer{background:var(--surface-1)}
/* the solid footer sits on surface-1, so the mark's hole has to as well */
[data-bars="solid"] .dv-footer__dot::after{background:var(--surface-1)}

/* ---------- element hosts ----------
   Two shapes, on purpose:

   - Structural elements ARE the box. The class lands on the host, so there is
     no wrapper between your grid/flex parent and the component.
   - Controls that must own a real <button>/<input>/<label> step out of layout
     with display:contents, so the native element is what your parent sees.

   Both mean an app never writes .dv-* markup by hand. */
dv-button,dv-icon-button,dv-input,dv-switch,dv-chip{display:contents}
dv-slider{display:block}
/* a linked card hands its box to an inner <a>, so the host steps aside too */
dv-card[href]{display:contents}

/* Before the script upgrades them the hosts are empty. Keep them out of layout
   so a blocked script leaves no phantom gap — except the header, which
   reserves its height so a deferred (module) load causes no shift. */
dev-footer:not(:defined){display:none}
dev-header:not(:defined){display:block;height:74px}
dv-card:not(:defined),dv-badge:not(:defined),dv-tag:not(:defined),dv-tabs:not(:defined),dv-placeholder:not(:defined){visibility:hidden}

@media (prefers-reduced-motion:reduce){
  *,*::before,*::after{transition-duration:.01ms !important;animation-duration:.01ms !important}
}
