/* ============================================================================
   SKIN: "sharp" — Storenaut's second visual version.

   HOW IT WORKS
   Always loaded, immediately after style.css, but every rule is scoped under
   :root[data-skin="sharp"]. Without that attribute it matches nothing and the
   app looks exactly as it always did. The attribute is rendered server-side
   from the ui_skin setting (admin flips it at /admin for everyone), and the ◧
   button in the chrome overrides it for one browser only, for previewing.

   WHAT IT CHANGES
   Neutrals, density and — on a wide screen — the shape of the navigation.
   The accent stays Storenaut gold, identical to the classic look, so the
   landing page, favicon, logo mark and brand emails all still match. What
   changes is everything around it: flat neutral greys instead of the blue-ink
   palette, hairline borders, 32px table rows, smaller type, and the topbar
   folded into a 216px sidebar.

   THE SIDEBAR
   No new nav markup. base.html's topbar is a flex row whose two halves are
   display:contents, so its children are already direct flex items — turning
   the container into a column puts the brand at the top, the links under it,
   and (via the existing .spacer) the account controls at the bottom. That is
   a sidebar. It applies at ≥1181px only; below that the existing ☰ drawer is
   left completely alone, because it already works and a second responsive
   strategy is how mobile bugs get made.

   TO REMOVE
   Delete this file, drop the <link>, the ◧ button and the .sidestores block
   from base.html, remove .sidestores from style.css, and drop skin-sharp.css
   from the ASSET_V tuple in app.py.
   ============================================================================ */

/* ---- tokens: dark -------------------------------------------------------- */
/* Flat neutral greys — no blue cast. The gold is untouched from classic. */
:root[data-skin="sharp"]{
  --bg:#0A0A0C; --bg2:#141519; --card:#101116; --line:rgba(255,255,255,.085);
  --txt:#ECEDEF; --muted:#8A8F98; --faint:#5E636C;
  /* Indigo, not the classic gold — sharp is its own identity. Only this skin
     changes; classic keeps gold, and so do the landing page, favicon, logo
     mark and the brand emails. */
  --accent:#8A90F0; --accent-btn:#8A90F0; --accent-ink:#0B0C14;
  --topbar:rgba(10,10,12,.88); --code-bg:#141519; --td-line:rgba(255,255,255,.05);
  --radius:9px;
  --line2:rgba(255,255,255,.16);
  --rowh:32px; --side:216px;
  /* Money state is the only other colour this look allows itself, so it gets its
     own steps rather than classic's — deeper and less neon against flat grey. */
  --ok:#3DBB8A; --warn:#D6A63F; --err:#E8695C;
}
/* ---- tokens: light ------------------------------------------------------- */
:root[data-skin="sharp"][data-theme="light"]{
  --bg:#FAFAFB; --bg2:#F4F5F6; --card:#FFFFFF; --line:rgba(11,13,17,.09);
  --txt:#0B0D11; --muted:#666D78; --faint:#959CA6;
  --accent:#4A52C4; --accent-btn:#4A52C4; --accent-ink:#FFFFFF;
  --topbar:rgba(250,250,251,.88); --code-bg:#F1F2F4; --td-line:rgba(11,13,17,.05);
  --line2:rgba(11,13,17,.15);
  --ok:#0E7A54; --warn:#8A6410; --err:#BE3125;
}
@media(prefers-color-scheme:light){
  :root[data-skin="sharp"]:not([data-theme]){
    --bg:#FAFAFB; --bg2:#F4F5F6; --card:#FFFFFF; --line:rgba(11,13,17,.09);
    --txt:#0B0D11; --muted:#666D78; --faint:#959CA6;
    --accent:#4A52C4; --accent-btn:#4A52C4; --accent-ink:#FFFFFF;
    --topbar:rgba(250,250,251,.88); --code-bg:#F1F2F4; --td-line:rgba(11,13,17,.05);
    --line2:rgba(11,13,17,.15);
    --ok:#0E7A54; --warn:#8A6410; --err:#BE3125;
    }
}

/* ---- global type --------------------------------------------------------- */
:root[data-skin="sharp"] body{font-size:13.5px;line-height:1.5;letter-spacing:-.09px}

/* ==========================================================================
   NAVIGATION — sidebar at ≥1181px, untouched ☰ drawer below
   ========================================================================== */
@media(min-width:1181px){
  :root[data-skin="sharp"] body{padding-left:var(--side)}
  :root[data-skin="sharp"] .topbar{
    position:fixed;left:0;top:0;bottom:0;width:var(--side);z-index:30;
    flex-direction:column;align-items:stretch;flex-wrap:nowrap;
    gap:1px;padding:10px 8px;overflow-y:auto;overscroll-behavior:contain;
    background:var(--bg2);border-right:1px solid var(--line);border-bottom:none;
    backdrop-filter:none;-webkit-backdrop-filter:none}
  /* thin scrollbar — a 216px column with a fat one loses real estate */
  :root[data-skin="sharp"] .topbar{scrollbar-width:thin}
  :root[data-skin="sharp"] .topbar::-webkit-scrollbar{width:6px}
  :root[data-skin="sharp"] .topbar::-webkit-scrollbar-thumb{
    background:var(--line2);border-radius:99px}

  :root[data-skin="sharp"] .brand{padding:5px 8px 12px;font-size:15px;gap:8px}
  :root[data-skin="sharp"] .mark{width:20px;height:20px;border-radius:6px}

  :root[data-skin="sharp"] .nav{flex-direction:column;margin-left:0;gap:1px}
  :root[data-skin="sharp"] .nav a{display:flex;align-items:center;gap:8px;
    padding:6px 9px;font-size:13px;font-weight:500;border-radius:7px}
  :root[data-skin="sharp"] .nav a .navpill{margin-left:auto}
  /* group heading + right-aligned counts: what turns a list of links into a
     navigation. Both are display:none in classic. */
  :root[data-skin="sharp"] .navgroup{display:block;font-size:10px;font-weight:600;
    letter-spacing:.7px;text-transform:uppercase;color:var(--faint);
    padding:14px 9px 5px}
  :root[data-skin="sharp"] .navct{display:block;margin-left:auto;font-size:11.5px;
    font-weight:500;color:var(--faint)}
  :root[data-skin="sharp"] .nav a.on .navct{color:var(--accent)}

  /* Every full-width control in the column: admin/demo forms, the switcher,
     the account links. They are direct flex children, so they stretch unless
     told otherwise — which is what we want, but their buttons need to follow. */
  :root[data-skin="sharp"] .topbar form{margin:0!important;width:100%}
  :root[data-skin="sharp"] .topbar form .btn{width:100%;text-align:center}
  :root[data-skin="sharp"] .topbar>.badge,
  :root[data-skin="sharp"] .topmenu>.badge{margin:6px 0 2px!important;text-align:center}
  :root[data-skin="sharp"] .storeswitch{width:100%;max-width:none;margin-left:0!important;
    margin-top:4px}

  /* the account cluster sits at the bottom, pushed by the existing .spacer */
  :root[data-skin="sharp"] .spacer{flex:1 0 12px}
  :root[data-skin="sharp"] .topmenu2{display:flex!important;flex-direction:column;
    gap:5px;align-items:stretch;padding-top:8px;border-top:1px solid var(--line)}
  :root[data-skin="sharp"] .topmenu2 .hint{font-size:11px;padding:0 4px;
    overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
  :root[data-skin="sharp"] .topmenu2 .btn{width:100%;text-align:center}

  /* the icon row — wrapper is display:contents in classic, so this is inert there */
  :root[data-skin="sharp"] .topicons{display:flex!important;gap:5px;
    padding:8px 2px 2px;border-top:1px solid var(--line);margin-top:2px}
  :root[data-skin="sharp"] .topicons .themebtn{flex:1}

  /* The notify panel must escape the sidebar's scroll clip, and 320px will not
     fit inside 216px. Fixed to the viewport, anchored beside the rail. */
  :root[data-skin="sharp"] .notify-panel{position:fixed;left:calc(var(--side) + 8px);
    right:auto;top:auto;bottom:12px;width:320px;max-height:70vh}

  /* The store list, hidden in classic (style.css), shown only here. It now lives
     INSIDE .nav, directly under the app-level links, so the rules that used to
     position it below the whole nav (margin-top, a top border) are gone — it is
     one more group in the rail, spaced like the others. */
  :root[data-skin="sharp"] .nav .sidestores{display:flex;flex-direction:column;gap:1px;
    margin:12px 0 2px}
  :root[data-skin="sharp"] .sidestores .sslabel{font-size:10px;font-weight:600;
    letter-spacing:1.1px;text-transform:uppercase;color:var(--faint);padding:0 9px 5px}
  :root[data-skin="sharp"] .sidestores a{display:flex;align-items:center;gap:8px;
    padding:5px 9px;border-radius:7px;
    font-size:12.5px;color:var(--muted);overflow:hidden;text-overflow:ellipsis;
    white-space:nowrap}
  :root[data-skin="sharp"] .sidestores a:hover{background:var(--card);color:var(--txt)}
  :root[data-skin="sharp"] .sidestores a.on{background:var(--card);color:var(--txt);font-weight:600}
  :root[data-skin="sharp"] .sidestores a.ssmore{color:var(--faint);font-size:12px;
    padding-left:24px}
  /* With the list in the rail the dropdown is a second way to do one thing. The
     old rule keyed on .sidestores being the select's SIBLING; it no longer is. */
  :root[data-skin="sharp"] .topmenu .storeswitch{display:none}
}

/* Health at a glance, off the notification feed the bell already computes: which
   store needs you, answered without opening any of them. Colour is not the only
   carrier — the row also gets a title — because a dot is 6px and some people
   can't tell these two hues apart. */
.ssdot{width:6px;height:6px;border-radius:99px;flex:none;background:var(--faint);
  opacity:.45}
.ssdot.warn{background:var(--warn);opacity:1}
.ssdot.err{background:var(--err);opacity:1;
  box-shadow:0 0 0 2.5px color-mix(in srgb,var(--err) 22%,transparent)}

/* chrome styling that applies at every width (drawer included) */
:root[data-skin="sharp"] .topbar{padding:8px 14px}
:root[data-skin="sharp"] .brand{font-size:14.5px;letter-spacing:-.4px}
:root[data-skin="sharp"] .nav a{font-size:13px;font-weight:500;padding:5px 10px;
  border-radius:7px;color:var(--muted)}
:root[data-skin="sharp"] .nav a:hover{background:var(--card);color:var(--txt)}
/* the current page is the one place the gold appears in the chrome */
:root[data-skin="sharp"] .nav a.on{background:color-mix(in srgb,var(--accent) 14%,transparent);
  color:var(--accent);font-weight:600}
:root[data-skin="sharp"] .themebtn{width:29px;height:29px;border-radius:7px;font-size:12.5px}
:root[data-skin="sharp"] .storeswitch{font-size:12.5px;padding:5px 8px;border-radius:7px;
  font-weight:500}

/* ---- page frame -----------------------------------------------------------
   The header is a breadcrumb, not a masthead: eyebrow and title run together
   on one line at reading size, with the page's controls already sitting
   opposite them in the existing .row-between. A 24px title stacked over a
   lede pushes the actual data below the fold, which is the thing this look
   exists to avoid. */
:root[data-skin="sharp"] .wrap{padding:14px 20px 60px}
:root[data-skin="sharp"] .eyebrow{font-size:13.5px;font-weight:500;
  letter-spacing:0;text-transform:none;color:var(--muted)}
:root[data-skin="sharp"] h1.title{font-size:15px;font-weight:650;
  letter-spacing:-.25px;margin:2px 0 0}
/* Run them together as a breadcrumb ONLY where the title is the very next
   element. The store page puts its h1 inside a flex row with a badge and a
   switcher, and an unconditional separator would leave a slash dangling at the
   end of the line above it. */
:root[data-skin="sharp"] .eyebrow:has(+ h1.title){display:inline}
:root[data-skin="sharp"] .eyebrow:has(+ h1.title)::after{content:" / ";
  color:var(--faint);font-weight:400}
:root[data-skin="sharp"] .eyebrow + h1.title{display:inline;font-size:13.5px;margin:0}
/* the explanatory line stays — it is real help — but stops being a headline */
:root[data-skin="sharp"] .lede{font-size:12.5px;color:var(--faint);margin-top:6px}
/* Section headings are labels, not announcements. The templates already write
   them in sentence case ("★ Trustpilot"); classic uppercases them in CSS. */
:root[data-skin="sharp"] .sec{font-size:13px;font-weight:600;letter-spacing:-.1px;
  text-transform:none;color:var(--txt);margin:22px 0 8px}
:root[data-skin="sharp"] .footer{font-size:11.5px}

/* ---- cards --------------------------------------------------------------- */
:root[data-skin="sharp"] .card{border-radius:9px;padding:14px 15px}
/* A card whose whole job is to hold a table becomes the table's frame: no
   padding, header row on the sunk fill, rows running edge to edge. .tscroll
   carries a -20px margin tuned to the old padding, so it has to be zeroed
   here or the table hangs outside its own border. */
:root[data-skin="sharp"] .card:has(>table),
:root[data-skin="sharp"] .card:has(>.tscroll){padding:0;overflow:hidden}
:root[data-skin="sharp"] .card:has(>.tscroll)>.tscroll{margin:0;padding:0}
:root[data-skin="sharp"] .card:has(>table)>table th,
:root[data-skin="sharp"] .card:has(>.tscroll) th{background:var(--bg2)}
/* …but a card that opens with a TITLE and then holds a table gets both rules: the
   table one zeroes the padding, and the header strip below pulls itself out by
   exactly that padding — so the title rendered 14px above its own card. Put the
   strip's own padding back when there is no card padding to borrow. */
:root[data-skin="sharp"] .card:has(>table)>h3:first-child,
:root[data-skin="sharp"] .card:has(>.tscroll)>h3:first-child,
:root[data-skin="sharp"] .card:has(>table)>.row-between:first-child:has(h3),
:root[data-skin="sharp"] .card:has(>.tscroll)>.row-between:first-child:has(h3){
  margin:0;padding:9px 15px}
/* Cards size to their content instead of stretching to match the tallest in the
   row — a panel with nothing in it should be short, not a tall empty box. */
:root[data-skin="sharp"] .grid{gap:10px;margin-top:12px;align-items:start}
:root[data-skin="sharp"] .client{border-radius:9px;padding:14px;transition:border-color .12s}
:root[data-skin="sharp"] .client:hover{transform:none;border-color:var(--line2)}
:root[data-skin="sharp"] .client-head{padding-bottom:8px;margin-bottom:11px}

/* ---- the summary tiles ----------------------------------------------------
   Figures sit in their own hairline box, one grid. An earlier version of this
   skin ran them as a text strip; eleven label-over-value pairs on one line read
   as a paragraph of numbers, and you lost which figure a change line belonged
   to. The boxes are this skin's own — flat card, hairline, 9px, tight padding —
   not classic's.
   The two KPI markups in the app disagree on order (portfolio puts .n first,
   the store tabs put .l first), so order: rather than flex-direction — the
   label sits on top either way. */
:root[data-skin="sharp"] .kpirow,
:root[data-skin="sharp"] .summary{
  display:grid;grid-template-columns:repeat(auto-fit,minmax(178px,1fr));
  /* two call sites set their own gap inline for the strip layout; a grid of
     boxes 26px apart reads as scattered, so the tile gap wins here */
  gap:8px!important;margin-top:14px;padding-bottom:0;border-bottom:0}
:root[data-skin="sharp"] .kpi,
:root[data-skin="sharp"] .summary .kpi{
  position:relative;display:flex;flex-direction:column;min-width:0;
  background:var(--card);border:1px solid var(--line);border-radius:var(--radius);
  padding:11px 13px 12px;transition:border-color .12s}
:root[data-skin="sharp"] .kpi:hover{border-color:var(--line2)}
:root[data-skin="sharp"] .kpi .l,
:root[data-skin="sharp"] .summary .kpi .l{order:1;font-size:11.5px;font-weight:500;
  color:var(--faint);letter-spacing:0;text-transform:none;margin:0;
  white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
:root[data-skin="sharp"] .kpi .n,
:root[data-skin="sharp"] .summary .kpi .n{order:2;font-size:21px;font-weight:600;
  letter-spacing:-.75px;margin-top:5px;line-height:1.15}
/* the change line sits under the figure — without an explicit order it would
   sort ahead of both of them, since the other two are the ones carrying one */
:root[data-skin="sharp"] .kpi .d,
:root[data-skin="sharp"] .summary .kpi .d{order:3}
/* The lines that carry context rather than a change ("6.5% of revenue ·
   Servicepoint") are sentences, not figures: let them wrap inside the tile
   instead of running out over its border on a narrow column. */
:root[data-skin="sharp"] .kpi .d:not(.chip){white-space:normal}

/* Net is the figure the page exists to produce, so its tile is the one that
   differs: filled ground, two columns, a bigger number. Nothing else gets a
   treatment — a page where every tile is emphasised has no emphasis. */
:root[data-skin="sharp"] .summary .kpi[data-metric="net"]{
  grid-column:span 2;background:var(--bg2);border-color:var(--line2)}
:root[data-skin="sharp"] .summary .kpi[data-metric="net"] .n{font-size:28px;letter-spacing:-1.1px}
:root[data-skin="sharp"] .summary .kpi[data-metric="net"] .l{color:var(--muted);font-weight:600}
/* Margin and profit per order, restated under Net. They are tiles of their own
   when you switch them on, but this is the one figure everyone reads and the
   two lines that qualify it belong next to it — not two tiles away. */
:root[data-skin="sharp"] .kpi .ksub{display:block;order:4;font-size:11px;
  color:var(--faint);margin-top:5px;font-variant-numeric:tabular-nums}

/* A period-on-period change is a chip in the corner, not a third line of text:
   it frees the line under the figure for the handful of tiles that carry real
   context (ROAS its break-even, Returns its rate). :has() reserves the corner
   only on the tiles that actually have a chip, so a long label elsewhere still
   gets the full width. */
:root[data-skin="sharp"] .kpi:has(.d.chip) .l{padding-right:60px}
:root[data-skin="sharp"] .kpi .d.chip{position:absolute;top:10px;right:11px;
  margin:0;padding:1px 5px;border-radius:5px;font-size:10.5px;font-weight:600;
  letter-spacing:0;color:var(--faint);background:var(--bg2)}
:root[data-skin="sharp"] .kpi .d.chip.up{color:var(--ok);
  background:color-mix(in srgb,var(--ok) 13%,transparent)}
:root[data-skin="sharp"] .kpi .d.chip.dn{color:var(--err);
  background:color-mix(in srgb,var(--err) 13%,transparent)}

/* ROAS is never read on its own — it is read against break-even. The bar puts
   the threshold in the tile: the marker is break-even, fixed at the middle, and
   the fill is the ratio to it, so "how far past break-even" looks the same on
   every store and every window. Capped at twice break-even. */
:root[data-skin="sharp"] .kpi .beb.on{display:block;order:2;position:relative;
  height:4px;border-radius:2px;background:var(--bg2);margin-top:9px}
:root[data-skin="sharp"] .kpi .beb i{position:absolute;left:0;top:0;bottom:0;
  border-radius:2px;background:var(--ok)}
:root[data-skin="sharp"] .kpi .beb.under i{background:var(--err)}
:root[data-skin="sharp"] .kpi .beb span{position:absolute;left:50%;top:-3px;bottom:-3px;
  width:2px;margin-left:-1px;background:var(--txt);opacity:.85}

@media(max-width:640px){
  :root[data-skin="sharp"] .kpirow,
  :root[data-skin="sharp"] .summary{
    grid-template-columns:repeat(auto-fit,minmax(138px,1fr));gap:7px!important}
  :root[data-skin="sharp"] .kpi,
  :root[data-skin="sharp"] .summary .kpi{padding:9px 11px 10px}
  :root[data-skin="sharp"] .kpi .n,
  :root[data-skin="sharp"] .summary .kpi .n{font-size:18px}
  :root[data-skin="sharp"] .summary .kpi[data-metric="net"] .n{font-size:24px}
}
@media(prefers-reduced-motion:reduce){
  :root[data-skin="sharp"] .kpi{transition:none}
}
/* The pipeline stage row keeps the flat, borderless treatment: it is a flow of
   counts through one funnel, not a set of independent figures, and boxing it
   would read as five unrelated tiles. */
:root[data-skin="sharp"] .stage{background:none;border:0;padding:0;text-align:left}
:root[data-skin="sharp"] .stage .n{font-size:19px;font-weight:600;letter-spacing:-.6px}
:root[data-skin="sharp"] .stage .l{font-size:11.5px;text-transform:none;letter-spacing:0;
  color:var(--faint)}
:root[data-skin="sharp"] .stageflow{gap:30px}
:root[data-skin="sharp"] .stage{border-radius:9px;padding:11px 8px}
:root[data-skin="sharp"] .stage .n{font-size:18px}

/* ---- tables -------------------------------------------------------------- */
:root[data-skin="sharp"] table{font-size:13px}
:root[data-skin="sharp"] th{font-size:11px;font-weight:600;padding:7px 11px;
  background:var(--bg2);text-transform:none;letter-spacing:0}
/* height on a table cell is a minimum, not a fix: single-line rows land on the
   32px rhythm, and a cell carrying a title + sub-line grows instead of having
   its two lines crushed against the row borders. The vertical padding is what
   makes that true — with 0 the multi-line case reads as two separate rows. */
:root[data-skin="sharp"] td{padding:6px 11px;height:var(--rowh);color:var(--muted)}
:root[data-skin="sharp"] td b,:root[data-skin="sharp"] td strong{color:var(--txt)}
:root[data-skin="sharp"] tr.pfrow:hover{background:var(--bg2)}
:root[data-skin="sharp"] .tscroll th.stick,
:root[data-skin="sharp"] .tscroll td.stick{background:var(--card)}
:root[data-skin="sharp"] .tscroll th.stick{background:var(--bg2)}
:root[data-skin="sharp"] .tscroll tr.pfrow:hover td.stick{background:var(--bg2)}
:root[data-skin="sharp"] .storelink{color:var(--txt);font-weight:600}
:root[data-skin="sharp"] .storelink:hover{color:var(--accent)}
:root[data-skin="sharp"] .pfcard{border-radius:9px;padding:11px 12px}
:root[data-skin="sharp"] .pfcard-net{font-size:15px;letter-spacing:-.4px}
:root[data-skin="sharp"] .thumb{border-radius:5px}

/* ---- buttons ------------------------------------------------------------- */
:root[data-skin="sharp"] .btn{font-size:13px;font-weight:600;padding:7px 14px;border-radius:7px}
:root[data-skin="sharp"] .btn.sm{padding:4px 9px;font-size:12px;border-radius:6px}
:root[data-skin="sharp"] .btn.ghost{color:var(--muted)}
:root[data-skin="sharp"] .btn.ghost:hover{color:var(--txt);box-shadow:inset 0 0 0 1px var(--line2)}
:root[data-skin="sharp"] .gbtn{border-radius:7px;font-size:13px;padding:8px 16px}

/* ---- badges -------------------------------------------------------------- */
:root[data-skin="sharp"] .badge{font-size:10px;font-weight:600;letter-spacing:.3px;
  padding:2px 7px;text-transform:none}
/* Translucent, not an opaque token: a neutral badge sits on both the page and a
   card, and an opaque --bg2 fill disappears against whichever of the two it is
   nearest. Classic solves it the same way, and this is why. */
:root[data-skin="sharp"] .b-idle{background:color-mix(in srgb,var(--muted) 20%,transparent);
  color:var(--muted)}
:root[data-skin="sharp"] .navpill{font-size:9.5px;font-weight:700}

/* ---- tabs & switchers ------------------------------------------------------
   One tab language for the whole app: a hairline-bordered group of cells divided
   by hairlines, the selected one filled with ink. It replaces four different
   treatments (underlined tabs, two pill bars, a bordered select) that all meant
   the same thing — "you are here, these are the alternatives".

   Ink rather than the accent for the selected cell: the accent is spent on the
   primary action and the current nav item, and a row of controls in which one
   cell glows indigo reads as a promotion rather than a state. */
:root[data-skin="sharp"] .tabbar,
:root[data-skin="sharp"] .subbar,
:root[data-skin="sharp"] .segmented,
:root[data-skin="sharp"] .winbar,
:root[data-skin="sharp"] .segwin{
  display:inline-flex;flex-wrap:nowrap;gap:0;padding:0;background:none;
  border:1px solid var(--line);border-radius:7px;max-width:100%;
  overflow-x:auto;scrollbar-width:none}
:root[data-skin="sharp"] .tabbar::-webkit-scrollbar,
:root[data-skin="sharp"] .subbar::-webkit-scrollbar,
:root[data-skin="sharp"] .segmented::-webkit-scrollbar,
:root[data-skin="sharp"] .winbar::-webkit-scrollbar,
:root[data-skin="sharp"] .segwin::-webkit-scrollbar{display:none}
:root[data-skin="sharp"] .tabbar{margin:16px 0 14px}
:root[data-skin="sharp"] .winbar{margin-bottom:14px}
:root[data-skin="sharp"] .tab,
:root[data-skin="sharp"] .subtab,
:root[data-skin="sharp"] .seg,
:root[data-skin="sharp"] .winbtn,
:root[data-skin="sharp"] .segwin-b{
  background:var(--card);color:var(--muted);border:0;border-right:1px solid var(--line);
  border-radius:0;margin:0;font-size:12.5px;font-weight:500;padding:5px 11px;
  white-space:nowrap;flex:none}
:root[data-skin="sharp"] .tab:last-child,
:root[data-skin="sharp"] .subtab:last-child,
:root[data-skin="sharp"] .seg:last-child,
:root[data-skin="sharp"] .winbtn:last-child,
:root[data-skin="sharp"] .segwin-b:last-child{border-right:none}
/* the group's own corners, on the children — the container has to stay
   overflow-x:auto for a 12-tab store page, so it can't clip them itself */
:root[data-skin="sharp"] .tab:first-child,
:root[data-skin="sharp"] .subtab:first-child,
:root[data-skin="sharp"] .seg:first-child,
:root[data-skin="sharp"] .winbtn:first-child,
:root[data-skin="sharp"] .segwin-b:first-child{border-radius:6px 0 0 6px}
:root[data-skin="sharp"] .tab:last-child,
:root[data-skin="sharp"] .subtab:last-child,
:root[data-skin="sharp"] .seg:last-child,
:root[data-skin="sharp"] .winbtn:last-child,
:root[data-skin="sharp"] .segwin-b:last-child{border-radius:0 6px 6px 0}
:root[data-skin="sharp"] .tab:hover,
:root[data-skin="sharp"] .subtab:hover,
:root[data-skin="sharp"] .seg:hover,
:root[data-skin="sharp"] .winbtn:hover,
:root[data-skin="sharp"] .segwin-b:hover{background:var(--bg2);color:var(--txt)}
:root[data-skin="sharp"] .tab.on,
:root[data-skin="sharp"] .subtab.on,
:root[data-skin="sharp"] .seg:has(input:checked),
:root[data-skin="sharp"] .winbtn.on,
:root[data-skin="sharp"] .segwin-b.on{background:var(--txt);color:var(--bg);font-weight:600}
/* the underline is the classic look's mechanism; here the fill is */
:root[data-skin="sharp"] .tab{border-bottom:0;margin-bottom:0}
:root[data-skin="sharp"] .tab.on{border-bottom-color:transparent}

/* ---- ⌘K quick-jump: a control in the rail, matching the mockup ------------- */
@media(min-width:1181px){
  :root[data-skin="sharp"] .cmdk-btn{display:flex;align-items:center;gap:7px;width:100%;
    margin:9px 0 2px;padding:5px 9px;border-radius:7px;border:1px solid var(--line);
    background:var(--card);color:var(--faint);font:inherit;font-size:12.5px;cursor:pointer}
  :root[data-skin="sharp"] .cmdk-btn:hover{border-color:var(--line2);color:var(--muted)}
  :root[data-skin="sharp"] .cmdk-btn kbd{margin-left:auto;font-family:ui-monospace,SFMono-Regular,Menlo,monospace;
    font-size:10px;color:var(--faint)}
}
:root[data-skin="sharp"] .cmdk-box{border-radius:10px}
:root[data-skin="sharp"] .cmdk-i{border-radius:6px;font-size:13px}
/* --bg2 is a hair off --card in this skin, so the selected row would be almost
   invisible; the accent tint is what marks the current item everywhere else. */
:root[data-skin="sharp"] .cmdk-i.on{background:color-mix(in srgb,var(--accent) 14%,transparent);
  color:var(--accent)}
:root[data-skin="sharp"] .cmdk-i.on em{color:var(--accent)}

/* ---- the change line under each portfolio figure ---------------------------- */
/* The colour has to be restated per state: this selector outweighs style.css's
   `.kpi .d.up`, so setting only the neutral colour here would silently strip the
   green and red off every change line in this skin. */
:root[data-skin="sharp"] .kpi .d{font-size:10.5px;margin-top:2px;color:var(--muted)}
:root[data-skin="sharp"] .kpi .d.up{color:var(--ok)}
:root[data-skin="sharp"] .kpi .d.dn{color:var(--err)}

/* ---- form controls -------------------------------------------------------- */
:root[data-skin="sharp"] .field input,:root[data-skin="sharp"] .field select{
  padding:8px 10px;border-radius:7px;background:var(--card)}
:root[data-skin="sharp"] .field label{font-size:12px;font-weight:500;margin-bottom:4px}
:root[data-skin="sharp"] .segmented{border-radius:8px;padding:2px}
:root[data-skin="sharp"] .seg{font-size:12.5px;padding:5px 11px;border-radius:6px}
:root[data-skin="sharp"] .winbar{border-radius:8px;padding:2px}
:root[data-skin="sharp"] .winbtn{font-size:12.5px;padding:5px 12px;border-radius:6px}
:root[data-skin="sharp"] .switch{font-size:11px;padding:4px 10px;letter-spacing:.3px}
:root[data-skin="sharp"] .styleopt{border-radius:8px;padding:9px 11px}
:root[data-skin="sharp"] .adv>summary{border-radius:7px;font-size:13px;padding:9px 12px}

/* ---- notes, hints, steps --------------------------------------------------- */
:root[data-skin="sharp"] .note,:root[data-skin="sharp"] .guide-note{border-radius:8px;
  padding:11px 13px;font-size:12.5px;border-left-width:2px}
:root[data-skin="sharp"] .hint{font-size:11.5px}
:root[data-skin="sharp"] .err,:root[data-skin="sharp"] .ok-msg{border-radius:8px;
  padding:9px 12px;font-size:12.5px}
:root[data-skin="sharp"] .steps li{font-size:12.5px}
:root[data-skin="sharp"] .jobbar{border-radius:8px;padding:7px 12px;font-size:12.5px}

/* ---- accent-tinted blocks flatten; hierarchy comes from the rule ---------- */
:root[data-skin="sharp"] .intel{background:var(--card);border-color:var(--line);
  border-radius:9px;padding:15px 16px}
:root[data-skin="sharp"] .intel-eyebrow{color:var(--muted);letter-spacing:1px}
:root[data-skin="sharp"] .intel-title{font-size:14.5px}
:root[data-skin="sharp"] .intel-body{font-size:12.5px}
:root[data-skin="sharp"] .signal{font-size:11.5px;padding:3px 9px;font-weight:500}
:root[data-skin="sharp"] .signal::before{color:var(--muted)}
:root[data-skin="sharp"] .alert-card{background:var(--card);
  border-color:color-mix(in srgb,var(--warn) 32%,var(--line))}
:root[data-skin="sharp"] .rw-hero{border-radius:9px;padding:12px 14px}
:root[data-skin="sharp"] .rw-hero .n{font-size:28px;letter-spacing:-.9px}

/* ---- moments, toasts, notifications ---------------------------------------- */
:root[data-skin="sharp"] .moment{border-radius:13px;padding:26px 24px 20px}
:root[data-skin="sharp"] .moment h2{font-size:17px}
:root[data-skin="sharp"] .moment p{font-size:13px}
:root[data-skin="sharp"] .toast{border-radius:9px;padding:10px 12px;font-size:12.5px;
  border-left-width:2px}
:root[data-skin="sharp"] .notify-panel{border-radius:9px}
:root[data-skin="sharp"] .nitem{padding:8px 9px}
:root[data-skin="sharp"] .nitem .ntitle{font-size:12px}

/* ---- guide + onboarding illustrations -------------------------------------- */
:root[data-skin="sharp"] .mock{border-radius:9px;box-shadow:none}
:root[data-skin="sharp"] .mock-btn{border-radius:6px}
:root[data-skin="sharp"] .mock-btn.hl{box-shadow:0 0 0 2px color-mix(in srgb,var(--accent) 26%,transparent)}
:root[data-skin="sharp"] .guide-toc a{border-radius:7px;font-size:12.5px;padding:5px 12px}
:root[data-skin="sharp"] .step .num{width:26px;height:26px;font-size:13px}
:root[data-skin="sharp"] .scopebox,:root[data-skin="sharp"] .scope-copy{border-radius:8px}

/* ---- panels: the card header strip, applied everywhere ---------------------
   The mockup's defining card treatment: the title sits in a recessed strip at
   the top of the card rather than floating in the body. Scoped to an h3 that is
   the card's FIRST child, so a card that opens with a table or a form is left
   alone. The negative margin pulls the strip out to the card's edges, which is
   why it has to match .card's own padding exactly. */
/* Two header shapes account for nearly every card in the app: 46 open with a
   bare <h3>, 35 with a .row-between holding the title plus a badge or button.
   Both get the strip, or the treatment lands on some cards and not others and
   reads as a bug. The :has(h3) guard keeps it off .row-between rows that are
   really control bars rather than headers. */
:root[data-skin="sharp"] .card>h3:first-child,
:root[data-skin="sharp"] .card>.row-between:first-child:has(h3){
  margin:-14px -15px 0;padding:9px 15px;background:var(--bg2);
  border-bottom:1px solid var(--line);font-size:13px!important;font-weight:600;
  letter-spacing:-.15px;color:var(--txt)}
:root[data-skin="sharp"] .card>.row-between:first-child:has(h3) h3{
  font-size:13px!important;font-weight:600;margin:0}
/* the meta line that usually follows a title joins the header visually */
:root[data-skin="sharp"] .card>h3:first-child + .hint,
:root[data-skin="sharp"] .card>.row-between:first-child:has(h3) + .hint{
  margin:0 -15px;padding:7px 15px;background:var(--bg2);
  border-bottom:1px solid var(--line);color:var(--faint)}
:root[data-skin="sharp"] .card>h3:first-child + .hint + .panel-list,
:root[data-skin="sharp"] .card>h3:first-child + .panel-list{margin-top:0}
/* rows run to the card's edges so the strip and the list share one grid */
:root[data-skin="sharp"] .panel-list{margin:0 -15px}
:root[data-skin="sharp"] .panel-row{padding:8px 15px}
:root[data-skin="sharp"] .panel-row:hover{background:var(--bg2);color:var(--txt)}
:root[data-skin="sharp"] .panel-row:first-child{border-top:none}
:root[data-skin="sharp"] .pr-body b{font-size:13px}
:root[data-skin="sharp"] .pr-body span{font-size:11.5px}
:root[data-skin="sharp"] .pr-val{font-size:11.5px;font-weight:600}
/* a card that is only a strip + list needs no bottom padding */
:root[data-skin="sharp"] .card:has(>.panel-list:last-child){padding-bottom:0}

/* ---- the ◧ button reads as active while the skin is on --------------------- */
:root[data-skin="sharp"] #skin-btn{color:var(--accent);border-color:var(--accent)}

/* ---- locked signposts in the sidebar ---------------------------------------
   All that is left of the old "the store's panels live in the rail" idea: the
   Advanced features that have no pane to switch to yet. The store's real
   sections went back to the page's tab bar, which is why `.tabbar.railed` and
   the `.subbar` suppression that used to live here are gone — hiding the bar
   only made sense while something else was carrying it. */
@media(min-width:1181px){
  :root[data-skin="sharp"] .navsection{display:flex;align-items:center;gap:6px}
}
:root[data-skin="sharp"] a.navsection,
:root[data-skin="sharp"] a.navsection:first-child,
:root[data-skin="sharp"] a.navsection:last-child{
  background:none;border:0;border-radius:7px;padding:5px 9px;margin:0;
  color:var(--muted);font-size:12.5px;font-weight:500;white-space:normal;flex:none}
:root[data-skin="sharp"] a.navsection:hover{background:var(--card);color:var(--txt)}
:root[data-skin="sharp"] a.navsection.on{background:var(--card);color:var(--accent);
  font-weight:600;box-shadow:inset 2px 0 0 var(--accent)}
:root[data-skin="sharp"] .navsoon,
:root[data-skin="sharp"] .navlocked{color:var(--faint);cursor:default;
  padding:5px 9px;font-size:12.5px;font-weight:500}

/* ---- foldable sidebar sections --------------------------------------------
   The fold state is applied to the links themselves (see base.html: the nav is a
   flat list, so a "group" is everything between two headings). This has to out-
   specify the .navsection display:flex above, hence the long selector rather
   than an !important. */
:root[data-skin="sharp"] .nav .navhidden,
:root[data-skin="sharp"] .nav a.navhidden,
:root[data-skin="sharp"] .nav span.navhidden{display:none}
:root[data-skin="sharp"] .navgroup{display:flex;align-items:center;cursor:pointer;
  user-select:none}
:root[data-skin="sharp"] .navgroup:hover{color:var(--muted)}
:root[data-skin="sharp"] .navgroup:focus-visible{outline:1px solid var(--accent);
  outline-offset:2px;border-radius:5px}
:root[data-skin="sharp"] .navchev{margin-left:auto;font-size:12px;line-height:1;
  transition:transform .15s ease}
:root[data-skin="sharp"] .navgroup.folded .navchev{transform:rotate(-90deg)}

/* ---- store Overview: the trading strip + signal cards -----------------------
   The shared rules in style.css do the work; sharp only tightens them to the
   density the rest of this skin runs at, and swaps the radius. */
:root[data-skin="sharp"] .ovstrip{border-radius:var(--radius)}
:root[data-skin="sharp"] .ovtile{padding:11px 14px 10px}
:root[data-skin="sharp"] .ovtile .l{font-size:10px;letter-spacing:.85px}
:root[data-skin="sharp"] .ovtile .n{font-size:21px;letter-spacing:-.75px}
:root[data-skin="sharp"] .ovtile .d{font-size:11px}
:root[data-skin="sharp"] .ovcard{padding:14px 16px;gap:6px;min-height:138px}
:root[data-skin="sharp"] .ovcard .h .t{font-size:13.5px}
:root[data-skin="sharp"] .ovcard .d{font-size:12.5px}
:root[data-skin="sharp"] .ovcard .big{font-size:25px}

/* ---- a tab the rail is carrying ------------------------------------------
   Customer service has a permanent group in the sidebar, so its tab would be
   the same six words twice on a wide screen. It is hidden HERE rather than
   dropped from the template, because `.navsection` is display:none in classic
   and under 1181px — the two places the rail does not exist. Delete the tab and
   the whole feature becomes unreachable there.

   Scoped to `.tab.railed` alone: this is not a return of the old `.tabbar.railed`
   that hid the entire bar. Ads, Products, P&L and the rest keep their tabs. */
@media(min-width:1181px){
  :root[data-skin="sharp"] .tabbar .tab.railed,
  :root[data-skin="sharp"] .subbar.railed{display:none}
}
