/* Harbor tokens. Apps use semantic tokens only, never a raw value.
   Layers let any app override without specificity fights. */
@layer hb.tokens, hb.base, hb.components;

/* Fonts download only if a page actually uses them. */
@font-face{font-family:"Bitter";src:url("fonts/bitter.woff2") format("woff2");font-weight:100 900;font-display:swap}
@font-face{font-family:"Source Sans 3";src:url("fonts/source-sans-3.woff2") format("woff2");font-weight:200 900;font-display:swap}
@font-face{font-family:"Geist Mono";src:url("fonts/geist-mono.woff2") format("woff2");font-weight:100 900;font-display:swap}

@layer hb.tokens{
:root{
  color-scheme:light dark;

  /* Hover and press tints work on every ground */
  --hover:light-dark(rgb(20 30 30/.06),rgb(255 255 255/.07));
  --press:light-dark(rgb(20 30 30/.11),rgb(255 255 255/.12));

  /* Accent: Sky (chosen by Vincent 2026-11-01). Means "interactive or selected", nothing else */
  --accent:light-dark(#3876b0,#4a9be8);
  --accent-text:light-dark(#2e6090,#72b1ed);
  --on-accent:light-dark(#ffffff,#101214);
  --accent-hover:color-mix(in oklab,var(--accent) 88%,light-dark(#000,#fff));
  --accent-soft:var(--press); /* selected fill: neutral, so colored text stays readable on it */

  /* Status: means "state of a thing"; always paired with a word or icon */
  --ok:light-dark(#1d5c22,#7fd16f);
  --warn:light-dark(#6c4603,#efc04a);
  --bad:light-dark(#a01632,#ff8f9b);
  --info:light-dark(#184f9f,#86b9ff);
  --on-bad:light-dark(#ffffff,#2b0509);
  --ok-soft:color-mix(in oklab,var(--ok) 16%,transparent);
  --warn-soft:color-mix(in oklab,var(--warn) 16%,transparent);
  --bad-soft:color-mix(in oklab,var(--bad) 16%,transparent);
  --info-soft:color-mix(in oklab,var(--info) 16%,transparent);

  /* Type */
  --font:"Source Sans 3",system-ui,sans-serif;
  --font-head:"Bitter",Georgia,serif;
  --head-weight:600;
  --head-track:-.005em;
  --mono:"Geist Mono",ui-monospace,"SF Mono",Menlo,monospace;
  --fs-xs:12px;--fs-sm:13px;--fs-md:14px;--fs-lg:16px;--fs-xl:20px;--fs-2xl:28px;--fs-3xl:40px;

  /* Space: 4px base */
  --s-1:4px;--s-2:8px;--s-3:12px;--s-4:16px;--s-5:20px;--s-6:24px;--s-8:32px;--s-10:40px;--s-12:48px;--s-16:64px;

  /* Shape: small, crisp corners */
  --r-sm:3px;--r-md:4px;--r-lg:6px;--r-full:999px;

  /* Density: one control height drives every control */
  --ctl:38px;--ctl-sm:calc(var(--ctl) - 8px);--ctl-lg:calc(var(--ctl) + 6px);--row:calc(var(--ctl) + 6px);

  /* Elevation: only things floating above the page have a shadow */
  --shadow-1:0 1px 2px light-dark(rgb(0 0 0/.1),rgb(0 0 0/.35));
  --shadow-2:0 6px 20px light-dark(rgb(0 0 0/.14),rgb(0 0 0/.45));
  --shadow-3:0 18px 50px light-dark(rgb(0 0 0/.22),rgb(0 0 0/.55));

  /* Motion: nothing over 180ms; press is instant; leaving is faster than arriving */
  --t-fast:80ms;--t-base:120ms;--t-slow:180ms;
  --ease:cubic-bezier(.2,.7,.3,1);
}
[data-theme="light"]{color-scheme:light}
[data-theme="dark"]{color-scheme:dark}
@media (pointer:coarse){:root{--ctl:40px}}
@media (prefers-reduced-motion:reduce){:root{--t-fast:0ms;--t-base:0ms;--t-slow:0ms}}

/* Ground: neutral gray (from v0.1, Vincent 2026-11-01) */
:root{
  --bg:light-dark(#f3f4f3,#121416);
  --surface:light-dark(#ffffff,#191c1f);
  --raised:light-dark(#ffffff,#212529);
  --sunken:light-dark(#f0f2f1,#0d0f10);
  --border:light-dark(#dfe2e1,#2a2f33);
  --border-strong:light-dark(#c3c8c6,#3d4348);
  --text:light-dark(#16191a,#eceeee);
  --text-2:light-dark(#4f5759,#aab1b4);
  --text-3:light-dark(#5a6265,#9aa2a6);
}

}
@layer hb.base{
*,*::before,*::after{box-sizing:border-box}
html{-webkit-text-size-adjust:100%}
body{margin:0;background:var(--bg);color:var(--text);font:400 var(--fs-md)/1.45 var(--font);-webkit-font-smoothing:antialiased}
h1,h2,h3,h4,p{margin:0}
button,input,select,textarea{font:inherit;color:inherit}
a{color:var(--accent-text);text-decoration:none}
a:hover{text-decoration:underline}
:focus-visible{outline:2px solid var(--accent);outline-offset:2px}
::selection{background:var(--accent-soft)}
code,kbd,.hb-mono{font-family:var(--mono);font-size:.92em}
.hb-num{font-variant-numeric:tabular-nums}
.hb-display,.hb-h1,.hb-h2,.hb-h3,.hb-h4{font-family:var(--font-head);font-weight:var(--head-weight);letter-spacing:var(--head-track)}
.hb-display{font-size:var(--fs-3xl);line-height:1.1}
.hb-h1{font-size:var(--fs-2xl);line-height:1.15}
.hb-h2{font-size:var(--fs-xl);line-height:1.25}
.hb-h3{font-size:var(--fs-lg);line-height:1.3}
.hb-h4{font-size:var(--fs-md);line-height:1.35}
.hb-small{font-size:var(--fs-sm)}
.hb-caption{font-size:var(--fs-xs);line-height:1.35}
.hb-muted{color:var(--text-2)}
.hb-faint{color:var(--text-3)}
.hb-icon{width:16px;height:16px;flex:none;fill:none;stroke:currentColor;stroke-width:1.75;stroke-linecap:round;stroke-linejoin:round}
.hb-icon--lg{width:20px;height:20px}
}

@layer hb.components{
/* Button */
.hb-btn{display:inline-flex;align-items:center;justify-content:center;gap:var(--s-2);height:var(--ctl);padding:0 var(--s-3);border:1px solid var(--border-strong);border-radius:var(--r-md);background:var(--surface);color:var(--text);font-size:var(--fs-md);font-weight:500;line-height:1;white-space:nowrap;cursor:pointer;text-decoration:none;transition:background-color var(--t-fast),border-color var(--t-fast),color var(--t-fast)}
.hb-btn:hover{background:color-mix(in srgb,var(--text) 6%,var(--surface));text-decoration:none}
.hb-btn:active{background:color-mix(in srgb,var(--text) 11%,var(--surface));transform:translateY(.5px)}
.hb-btn--primary{background:var(--accent);border-color:transparent;color:var(--on-accent);font-weight:600}
.hb-btn--primary:hover{background:var(--accent-hover)}
.hb-btn--primary:active{background:var(--accent)}
.hb-btn--ghost{background:transparent;border-color:transparent;color:var(--text-2)}
.hb-btn--ghost:hover{background:var(--hover);color:var(--text)}
.hb-btn--ghost:active{background:var(--press)}
.hb-btn--danger{color:var(--bad);border-color:color-mix(in oklab,var(--bad) 45%,transparent)}
.hb-btn--danger:hover{background:var(--bad-soft)}
.hb-btn--danger:active{background:var(--bad);color:var(--on-bad)}
.hb-btn--sm{height:var(--ctl-sm);padding:0 var(--s-2);font-size:var(--fs-sm);border-radius:var(--r-sm)}
.hb-btn--lg{height:var(--ctl-lg);padding:0 var(--s-4);font-size:var(--fs-lg)}
.hb-btn--icon{width:var(--ctl);padding:0}
.hb-btn--icon.hb-btn--sm{width:var(--ctl-sm)}
.hb-btn--block{width:100%}
.hb-btn:disabled,.hb-btn[aria-disabled="true"]{opacity:.45;pointer-events:none}
.hb-btn[aria-busy="true"]{pointer-events:none;color:transparent;position:relative}
.hb-btn[aria-busy="true"]::after{content:"";position:absolute;width:14px;height:14px;border-radius:50%;border:2px solid var(--text-3);border-top-color:var(--text);animation:hb-spin .6s linear infinite}
.hb-btn--primary[aria-busy="true"]::after{border-color:color-mix(in srgb,var(--on-accent) 35%,transparent);border-top-color:var(--on-accent)}
@keyframes hb-spin{to{transform:rotate(360deg)}}

/* Fields */
.hb-field{display:flex;flex-direction:column;gap:var(--s-1);min-width:0}
.hb-label{font-size:var(--fs-sm);font-weight:500}
.hb-hint{font-size:var(--fs-xs);color:var(--text-3)}
.hb-error{font-size:var(--fs-xs);color:var(--bad)}
.hb-input,.hb-select,.hb-textarea{width:100%;height:var(--ctl);padding:0 var(--s-3);background:var(--surface);border:1px solid var(--border-strong);border-radius:var(--r-md);transition:border-color var(--t-fast)}
.hb-textarea{height:auto;min-height:calc(var(--ctl)*2.4);padding:var(--s-2) var(--s-3);line-height:1.45;resize:vertical;display:block}
.hb-input::placeholder,.hb-textarea::placeholder{color:var(--text-3)}
.hb-input:hover,.hb-select:hover,.hb-textarea:hover{border-color:var(--text-3)}
.hb-input:focus,.hb-select:focus,.hb-textarea:focus{outline:2px solid var(--accent);outline-offset:-1px;border-color:transparent}
.hb-input[aria-invalid="true"]{border-color:var(--bad)}
.hb-input:disabled{opacity:.5;background:transparent}
.hb-select{appearance:none;padding-right:var(--s-8);cursor:pointer;background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16' fill='none' stroke='%23999' stroke-width='2' stroke-linecap='round' stroke-linejoin='round' viewBox='0 0 24 24'%3E%3Cpath d='m6 9 6 6 6-6'/%3E%3C/svg%3E");background-repeat:no-repeat;background-position:right 10px center}
.hb-select option{background:var(--raised);color:var(--text)}
.hb-search{position:relative;display:flex;align-items:center;min-width:0}
.hb-search .hb-icon{position:absolute;left:10px;color:var(--text-3);pointer-events:none}
.hb-search .hb-input{padding-left:32px}

/* Select: the native element keeps the value and form behaviour; ds.js draws the same trigger and list as a menu */
.hb-select-native{position:absolute;width:1px;height:1px;opacity:0;pointer-events:none}
.hb-select-btn{width:100%;justify-content:space-between;font-weight:500;text-align:left}
.hb-select-btn span{overflow:hidden;text-overflow:ellipsis}
.hb-select-btn svg{flex:none;width:16px;height:16px;fill:none;stroke:currentColor;stroke-width:1.75;stroke-linecap:round;stroke-linejoin:round}
.hb-listbox{max-height:280px;overflow-y:auto}
.hb-menu button[role=option]{justify-content:space-between;font-size:var(--fs-md);font-weight:500}
.hb-menu button[role=option]:focus-visible{outline:none;background:var(--hover)}
.hb-menu button[aria-selected=true]{background:var(--accent-soft);color:var(--accent-text)}
.hb-menu button[aria-selected=true]::after{content:"";width:5px;height:10px;margin:-2px 3px 0;border:solid currentColor;border-width:0 2px 2px 0;transform:rotate(42deg)}

/* Check, radio, switch: native inputs, no JS */
.hb-check{display:inline-flex;align-items:center;gap:var(--s-2);cursor:pointer;min-height:24px}
.hb-check input{appearance:none;flex:none;margin:0;width:18px;height:18px;border:1px solid var(--border-strong);border-radius:var(--r-sm);background:var(--surface);cursor:pointer;transition:background-color var(--t-fast),border-color var(--t-fast)}
.hb-check input:hover{border-color:var(--text-3)}
.hb-check input[type=radio]{border-radius:50%}
.hb-check input:checked{background:var(--accent);border-color:var(--accent)}
.hb-check input[type=checkbox]:checked::after{content:"";display:block;width:5px;height:10px;margin:2px 0 0 5.5px;border:solid var(--on-accent);border-width:0 2px 2px 0;transform:rotate(42deg)}
.hb-check input[type=radio]:checked::after{content:"";display:block;width:6px;height:6px;margin:5px;border-radius:50%;background:var(--on-accent)}
.hb-check:has(:disabled){color:var(--text-3);cursor:not-allowed}
.hb-switch{display:inline-flex;align-items:center;gap:var(--s-2);cursor:pointer}
.hb-switch input{appearance:none;flex:none;margin:0;width:34px;height:20px;border-radius:var(--r-full);background:var(--border-strong);position:relative;cursor:pointer;transition:background-color var(--t-fast)}
.hb-switch input::after{content:"";position:absolute;top:2px;left:2px;width:16px;height:16px;border-radius:50%;background:#fff;box-shadow:var(--shadow-1);transition:transform var(--t-base) var(--ease)}
.hb-switch input:checked{background:var(--accent)}
.hb-switch input:checked::after{transform:translateX(14px);background:var(--on-accent)}
.hb-switch input:disabled,.hb-check input:disabled{opacity:.45;cursor:not-allowed}

/* Slider */
.hb-slider{--v:50;appearance:none;display:block;width:100%;height:20px;margin:0;background:none;cursor:pointer}
.hb-slider::-webkit-slider-runnable-track{height:4px;border-radius:2px;background:linear-gradient(to right,var(--accent) calc(var(--v)*1%),var(--border-strong) 0)}
.hb-slider::-moz-range-track{height:4px;border-radius:2px;background:var(--border-strong)}
.hb-slider::-moz-range-progress{height:4px;border-radius:2px;background:var(--accent)}
.hb-slider::-webkit-slider-thumb{appearance:none;width:16px;height:16px;margin-top:-6px;border-radius:50%;background:var(--text);border:3px solid var(--surface);box-shadow:0 0 0 1px var(--border-strong)}
.hb-slider::-moz-range-thumb{width:10px;height:10px;border-radius:50%;background:var(--text);border:3px solid var(--surface);box-shadow:0 0 0 1px var(--border-strong)}

.hb-slider:disabled{cursor:not-allowed;opacity:.4;--v:0!important}
.hb-slider:disabled::-moz-range-progress{background:transparent}

/* Segmented: exclusive choice, native radios */
.hb-seg{display:inline-flex;padding:2px;gap:2px;background:var(--hover);border-radius:var(--r-md)}
.hb-seg label{cursor:pointer}
.hb-seg input{position:absolute;opacity:0;pointer-events:none}
.hb-seg span{display:flex;align-items:center;gap:6px;height:calc(var(--ctl) - 4px);padding:0 var(--s-3);border-radius:calc(var(--r-md) - 2px);font-size:var(--fs-sm);font-weight:500;color:var(--text-2);white-space:nowrap;transition:color var(--t-fast)}
.hb-seg label:hover span{color:var(--text)}
.hb-seg input:checked+span{background:var(--raised);color:var(--text);box-shadow:var(--shadow-1)}
.hb-seg input:focus-visible+span{outline:2px solid var(--accent);outline-offset:1px}

/* Tabs */
.hb-tabs{display:flex;gap:var(--s-1);border-bottom:1px solid var(--border);overflow-x:auto;scrollbar-width:none}
.hb-tab{appearance:none;background:none;border:0;border-bottom:2px solid transparent;margin-bottom:-1px;height:calc(var(--ctl) + 2px);padding:0 var(--s-3);color:var(--text-2);font-weight:500;cursor:pointer;white-space:nowrap;transition:color var(--t-fast)}
.hb-tab:hover{color:var(--text)}
.hb-tab[aria-selected="true"]{color:var(--text);border-bottom-color:var(--accent)}

/* Badge and status */
.hb-badge{display:inline-flex;align-items:center;gap:5px;height:22px;padding:0 var(--s-2);border-radius:var(--r-full);background:var(--hover);color:var(--text-2);font-size:var(--fs-xs);font-weight:550;white-space:nowrap}
.hb-badge--accent{background:var(--accent-soft);color:var(--accent-text)}
.hb-badge--ok{background:var(--ok-soft);color:var(--ok)}
.hb-badge--warn{background:var(--warn-soft);color:var(--warn)}
.hb-badge--bad{background:var(--bad-soft);color:var(--bad)}
.hb-badge--info{background:var(--info-soft);color:var(--info)}
.hb-dot{display:inline-block;width:7px;height:7px;flex:none;border-radius:50%;background:currentColor}
.hb-dot--live{animation:hb-pulse 1.6s steps(2,jump-none) infinite}
@keyframes hb-pulse{50%{opacity:.35}}
.hb-status{display:inline-flex;align-items:center;gap:6px;font-size:var(--fs-sm)}
.hb-status--ok .hb-dot{color:var(--ok)}.hb-status--warn .hb-dot{color:var(--warn)}.hb-status--bad .hb-dot{color:var(--bad)}.hb-status--off .hb-dot{color:var(--text-3)}

/* Card */
.hb-card{background:var(--surface);border:1px solid var(--border);border-radius:var(--r-lg);min-width:0}
.hb-card__head{display:flex;align-items:center;justify-content:space-between;gap:var(--s-3);padding:var(--s-3) var(--s-4);border-bottom:1px solid var(--border);min-height:calc(var(--ctl) + 16px)}
.hb-card__body{padding:var(--s-4)}
.hb-card--link{display:block;color:inherit;transition:border-color var(--t-fast)}
.hb-card--link:hover{border-color:var(--border-strong);text-decoration:none}
.hb-stat{display:flex;flex-direction:column;gap:2px}
.hb-stat__value{font-size:var(--fs-xl);font-weight:600;font-variant-numeric:tabular-nums;letter-spacing:-.01em}
.hb-stat__label{font-size:var(--fs-xs);color:var(--text-2)}

/* Table */
.hb-table-wrap{overflow-x:auto}
.hb-table{width:100%;border-collapse:collapse;font-size:var(--fs-md)}
.hb-table th{height:calc(var(--ctl) - 2px);padding:0 var(--s-4);text-align:left;font-size:var(--fs-xs);font-weight:550;color:var(--text-2);border-bottom:1px solid var(--border);white-space:nowrap}
.hb-table td{height:var(--row);padding:0 var(--s-4);border-bottom:1px solid var(--border);white-space:nowrap}
.hb-table tbody tr:last-child td{border-bottom:0}
.hb-table tbody tr:hover{background:var(--hover)}
.hb-table tr[aria-selected="true"]{background:var(--accent-soft)}
.hb-table .num{text-align:right;font-variant-numeric:tabular-nums}
.hb-table .grow{width:100%}
.hb-sort{display:inline-flex;align-items:center;gap:4px;color:var(--text)}

/* List */
.hb-list{display:flex;flex-direction:column;list-style:none;margin:0;padding:0}
.hb-item{display:flex;align-items:center;gap:var(--s-3);min-height:var(--row);padding:var(--s-1) var(--s-3);border-radius:var(--r-md);color:inherit;min-width:0;cursor:pointer;transition:background-color var(--t-fast)}
.hb-item:hover{background:var(--hover);text-decoration:none}
.hb-item[aria-current]{background:var(--accent-soft);color:var(--accent-text);font-weight:550}
.hb-item__main{flex:1;min-width:0}
.hb-truncate{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}

/* Notice */
.hb-notice{display:flex;gap:var(--s-3);padding:var(--s-3);border-radius:var(--r-md);background:var(--hover);font-size:var(--fs-sm);align-items:flex-start}
.hb-notice>.hb-icon{margin-top:1px}
.hb-notice>div{flex:1;min-width:0}
.hb-notice--ok{background:var(--ok-soft)}.hb-notice--ok>.hb-icon{color:var(--ok)}
.hb-notice--warn{background:var(--warn-soft)}.hb-notice--warn>.hb-icon{color:var(--warn)}
.hb-notice--bad{background:var(--bad-soft)}.hb-notice--bad>.hb-icon{color:var(--bad)}
.hb-notice--info{background:var(--info-soft)}.hb-notice--info>.hb-icon{color:var(--info)}

/* Progress, meter, skeleton */
.hb-progress{display:block;width:100%;height:6px;border-radius:3px;background:var(--hover);overflow:hidden}
.hb-progress>i{display:block;height:100%;background:var(--accent);transform:scaleX(calc(var(--v,0)/100));transform-origin:left;transition:transform var(--t-slow) var(--ease)}
.hb-progress--ok>i{background:var(--ok)}.hb-progress--warn>i{background:var(--warn)}.hb-progress--bad>i{background:var(--bad)}
.hb-progress--busy>i{width:30%;transform:none;border-radius:3px;animation:hb-slide 1.1s linear infinite}
@keyframes hb-slide{from{transform:translateX(-100%)}to{transform:translateX(340%)}}
.hb-skeleton{display:block;height:12px;border-radius:var(--r-sm);background:var(--hover)}
.hb-spinner{display:inline-block;width:16px;height:16px;border-radius:50%;border:2px solid var(--border-strong);border-top-color:var(--accent);animation:hb-spin .6s linear infinite}

/* Empty state */
.hb-empty{display:flex;flex-direction:column;align-items:center;gap:var(--s-2);padding:var(--s-10) var(--s-6);text-align:center}
.hb-empty>.hb-icon{width:24px;height:24px;color:var(--text-3)}

/* Avatar, kbd */
.hb-avatar{display:inline-grid;place-items:center;flex:none;width:28px;height:28px;border-radius:50%;background:var(--accent-soft);color:var(--accent-text);font-size:var(--fs-xs);font-weight:650}
.hb-avatar--lg{width:36px;height:36px;font-size:var(--fs-sm)}
kbd{display:inline-block;padding:0 5px;border:1px solid var(--border-strong);border-bottom-width:2px;border-radius:var(--r-sm);font-size:11px;line-height:17px;color:var(--text-2)}

/* Overlays: native dialog and popover. Fade plus a 4px rise; exits faster than it enters. */
.hb-dialog,.hb-menu{opacity:0;transition:opacity var(--t-fast),transform var(--t-fast),overlay var(--t-fast) allow-discrete,display var(--t-fast) allow-discrete}
.hb-dialog{transform:translateY(4px);width:min(440px,calc(100vw - 32px));padding:0;border:1px solid var(--border);border-radius:var(--r-lg);background:var(--raised);color:var(--text);box-shadow:var(--shadow-3)}
.hb-dialog[open]{opacity:1;transform:none;transition-duration:var(--t-base)}
@starting-style{.hb-dialog[open]{opacity:0;transform:translateY(4px)}}
.hb-dialog::backdrop{background:rgb(0 0 0/0);transition:background-color var(--t-fast),overlay var(--t-fast) allow-discrete,display var(--t-fast) allow-discrete}
.hb-dialog[open]::backdrop{background:rgb(0 0 0/.45)}
@starting-style{.hb-dialog[open]::backdrop{background:rgb(0 0 0/0)}}
.hb-dialog__body{padding:var(--s-5);display:flex;flex-direction:column;gap:var(--s-2)}
.hb-dialog__foot{display:flex;justify-content:flex-end;gap:var(--s-2);padding:var(--s-3) var(--s-5) var(--s-5)}
.hb-menu{transform:translateY(-2px);position:fixed;inset:auto;margin:0;min-width:180px;box-sizing:border-box;padding:var(--s-1);border:1px solid var(--border);border-radius:var(--r-md);background:var(--raised);color:var(--text);box-shadow:var(--shadow-2)}
.hb-menu:popover-open{opacity:1;transform:none;transition-duration:var(--t-base)}
@starting-style{.hb-menu:popover-open{opacity:0;transform:translateY(-2px)}}
.hb-menu button{display:flex;align-items:center;gap:var(--s-2);width:100%;height:calc(var(--ctl) - 4px);padding:0 var(--s-2);background:none;border:0;border-radius:var(--r-sm);color:inherit;text-align:left;font-size:var(--fs-md);font-weight:500;cursor:pointer}
.hb-menu button:hover{background:var(--hover)}
.hb-menu button .hb-shortcut{margin-left:auto;color:var(--text-3);font-size:var(--fs-xs)}
.hb-menu hr{border:0;border-top:1px solid var(--border);margin:var(--s-1) 0}
.hb-menu .is-danger{color:var(--bad)}

/* Tooltip: CSS only. Waits 300ms so it never flickers while the pointer passes. */
[data-tip]{position:relative}
[data-tip]::after{content:attr(data-tip);position:absolute;bottom:calc(100% + 6px);left:50%;translate:-50% 0;padding:3px 8px;border-radius:var(--r-sm);background:var(--text);color:var(--bg);font-size:var(--fs-xs);font-weight:500;line-height:1.4;white-space:nowrap;pointer-events:none;opacity:0;transition:opacity var(--t-fast);z-index:20}
[data-tip]:hover::after,[data-tip]:focus-visible::after{opacity:1;transition-delay:300ms}

/* Toast */
.hb-toasts{position:fixed;right:var(--s-4);bottom:var(--s-4);display:flex;flex-direction:column;gap:var(--s-2);z-index:100;width:min(340px,calc(100vw - 32px))}
.hb-toast{display:flex;align-items:center;gap:var(--s-2);padding:var(--s-3);background:var(--raised);border:1px solid var(--border);border-radius:var(--r-md);box-shadow:var(--shadow-2);font-size:var(--fs-sm);animation:hb-rise var(--t-base) var(--ease);transition:opacity var(--t-fast)}
.hb-toast.is-out{opacity:0}
.hb-toast span{flex:1}
@keyframes hb-rise{from{opacity:0;transform:translateY(4px)}}

/* App shell: same top bar in every app */
.hb-bar{display:flex;align-items:center;gap:var(--s-2);height:52px;padding:0 var(--s-3);background:var(--surface);border-bottom:1px solid var(--border)}
.hb-bar__name{display:flex;align-items:center;gap:var(--s-2);font-weight:600;padding-right:var(--s-3)}
.hb-bar__nav{display:flex;gap:2px;min-width:0;overflow-x:auto;scrollbar-width:none}
.hb-bar__nav a{display:flex;align-items:center;height:var(--ctl);padding:0 var(--s-3);border-radius:var(--r-md);color:var(--text-2);font-weight:500;white-space:nowrap;transition:background-color var(--t-fast),color var(--t-fast)}
.hb-bar__nav a:hover{background:var(--hover);color:var(--text);text-decoration:none}
.hb-bar__nav a[aria-current]{color:var(--accent-text);background:var(--accent-soft)}
.hb-bar__end{margin-left:auto;display:flex;align-items:center;gap:var(--s-2)}

/* Media tile */
.hb-tile{display:block;color:inherit;min-width:0}
.hb-tile:hover{text-decoration:none}
.hb-tile__art{position:relative;display:block;aspect-ratio:2/3;border-radius:var(--r-md);overflow:hidden;background:var(--hover);outline:2px solid transparent;outline-offset:2px;transition:outline-color var(--t-fast)}
.hb-tile:hover .hb-tile__art{outline-color:var(--accent)}
.hb-tile__title{display:block;margin-top:var(--s-2);font-size:var(--fs-sm);font-weight:500;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.hb-tile__meta{display:block;font-size:var(--fs-xs);color:var(--text-3)}
}
/* vboucher.xyz layout on top of Harbor (tokens + components come first in /app.css) */
@layer hb.app{
.top{position:sticky;top:0;z-index:5;justify-content:space-between;padding:0 var(--s-5)}
.brand{text-decoration:none;color:var(--text);font-family:var(--font-head);font-weight:var(--head-weight);font-size:var(--fs-lg);padding:0}
.mark{width:22px;height:22px;border-radius:var(--r-md);background:var(--accent);color:var(--on-accent);display:grid;place-items:center;font-size:13px;font-weight:700}
.top nav{display:flex;align-items:center;gap:var(--s-2);min-width:0}
.top nav form{margin:0}
.who{color:var(--text-2);font-size:var(--fs-sm);max-width:38vw;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.page{max-width:1080px;margin:0 auto;padding:var(--s-6) var(--s-5) var(--s-12)}
.sec-head{display:flex;align-items:center;gap:var(--s-3);margin-bottom:var(--s-4)}
.top-gap{margin-top:var(--s-4)}
.grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(320px,1fr));gap:var(--s-4)}
.stack{display:flex;flex-direction:column;gap:var(--s-3)}
.spread{display:flex;align-items:center;justify-content:space-between;gap:var(--s-3)}
.auth{display:grid;place-items:center;padding:12vh var(--s-5)}
.auth>.hb-card{width:100%;max-width:400px;padding:var(--s-6);display:flex;flex-direction:column;gap:var(--s-3)}
.hint{margin-top:var(--s-1)}
.or{display:flex;align-items:center;gap:var(--s-3);color:var(--text-3);font-size:var(--fs-sm)}
.or::before,.or::after{content:"";flex:1;height:1px;background:var(--border)}
.lamp-head{display:flex;align-items:center;gap:var(--s-3);min-width:0}
.lamp-dot{flex:none;width:12px;height:12px;border-radius:50%;background:var(--border-strong)}
.light.on .lamp-dot{background:var(--c)}
.lamp-label{display:flex;justify-content:space-between}
.lamp-label b{font-weight:400;color:var(--text-2);font-variant-numeric:tabular-nums}
.r-hue::-webkit-slider-runnable-track{background:linear-gradient(90deg,#f00,#ff0,#0f0,#0ff,#00f,#f0f,#f00)}
.r-hue::-moz-range-track{background:linear-gradient(90deg,#f00,#ff0,#0f0,#0ff,#00f,#f0f,#f00)}
.r-ct::-webkit-slider-runnable-track{background:linear-gradient(90deg,#cfe4ff,#fff3e0,#ffb46b)}
.r-ct::-moz-range-track{background:linear-gradient(90deg,#cfe4ff,#fff3e0,#ffb46b)}
.r-hue::-moz-range-progress,.r-ct::-moz-range-progress{background:transparent}
.lamp-sw{display:flex;gap:var(--s-2);flex-wrap:wrap}
.lamp-sw button{width:28px;height:28px;border-radius:var(--r-md);border:1px solid var(--border-strong);cursor:pointer;padding:0}
.lamp-sw button:hover{outline:2px solid var(--text);outline-offset:1px}
td.actions form{display:inline-block;margin:0 0 0 var(--s-2)}
td.actions{text-align:right}
@media (max-width:600px){.page{padding:var(--s-4) var(--s-4) var(--s-10)}.who{display:none}.top{padding:0 var(--s-3)}.grid{grid-template-columns:minmax(0,1fr)}.brand{font-size:var(--fs-md)}}
}
