/* ==========================================================================
   Kaliber 2026 — app controls

   IMPORTANT: unlike components.css, nothing in this file came out of the
   source page. The source is a brochure site — it has no text input, no
   select, no checkbox, no data table, no dialog. These were AUTHORED to the
   system's rules so an app surface can be built without inventing a second
   visual language.

   The rules they follow, all inherited:
     · zero radius, everywhere
     · a 2.5px charcoal keyline is the object; 2px is a part of one
     · focus is a thicker keyline plus a hard offset shadow, never a glow
     · amber = selected / checked / active. Pink = error. Sky = information.
     · every label is Space Mono 700, uppercase, tracked out
     · nothing transitions longer than 200ms except a bar filling

   Link it after styles.css:
     <link rel="stylesheet" href="styles.css">
     <link rel="stylesheet" href="app-controls.css">
   ========================================================================== */

/* ==========================================================================
   FIELDS
   ========================================================================== */

.k-field{display:flex;flex-direction:column;gap:.45rem;}

.k-label{
  font-family:var(--mono);font-weight:var(--w-mono);font-size:var(--t-micro-xs);
  letter-spacing:var(--track-micro);text-transform:uppercase;opacity:.7;
}
.k-label .req{color:var(--pink);margin-left:.25em;}

.k-hint{font-family:var(--mono);font-size:.62rem;line-height:1.5;opacity:.55;}
.k-error{
  font-family:var(--mono);font-weight:var(--w-mono);font-size:.62rem;line-height:1.5;
  color:var(--char);background:var(--pink);border:var(--line-3);
  padding:.3em .55em;align-self:flex-start;
}

/* the text input. Paper, charcoal keyline, mono. Sits flat until focused,
   then lifts onto its shadow — the same "object picked up" move as the pill. */
.k-input,.k-textarea,.k-select{
  width:100%;font-family:var(--mono);font-weight:var(--w-mono);font-size:var(--t-mono-sm);
  color:var(--char);background:var(--paper);
  border:var(--line);border-radius:var(--radius);
  padding:.65em .8em;line-height:1.4;
  transition:box-shadow .16s var(--ease-fill),transform .16s var(--ease-fill),background .16s;
}
.k-input::placeholder,.k-textarea::placeholder{color:var(--char);opacity:.35;}
.k-input:hover,.k-textarea:hover,.k-select:hover{background:var(--cream);}
.k-input:focus,.k-textarea:focus,.k-select:focus{
  outline:none;background:var(--paper);
  box-shadow:var(--drop-sm);transform:translate(-1px,-2px);
}
.k-input:disabled,.k-textarea:disabled,.k-select:disabled{
  background:var(--cream-2);opacity:.55;cursor:not-allowed;
}
.k-input[aria-invalid="true"],.k-textarea[aria-invalid="true"]{background:rgba(255,132,176,.18);}

.k-textarea{resize:vertical;min-height:6em;line-height:1.6;}

/* the select. Native element, custom caret drawn as a CSS triangle. */
.k-select{
  appearance:none;padding-right:2.2em;cursor:pointer;
  background-image:linear-gradient(45deg,transparent 50%,var(--char) 50%),
                   linear-gradient(135deg,var(--char) 50%,transparent 50%);
  background-position:calc(100% - 1.15em) center,calc(100% - .75em) center;
  background-size:.4em .4em,.4em .4em;
  background-repeat:no-repeat;
}

/* an input with a unit or prefix welded to it */
.k-inputgroup{display:flex;align-items:stretch;}
.k-inputgroup .k-input{border-right:none;}
.k-inputgroup .k-affix{
  display:flex;align-items:center;flex:none;
  font-family:var(--mono);font-weight:var(--w-mono);font-size:var(--t-micro);
  letter-spacing:.06em;text-transform:uppercase;
  background:var(--cream-2);border:var(--line);padding:0 .8em;
}

/* ==========================================================================
   CHOICE — checkbox, radio, switch
   All three are square except the radio's dot. Checked is amber, always.
   ========================================================================== */

.k-choice{
  display:inline-flex;align-items:flex-start;gap:.6em;cursor:pointer;
  font-family:var(--mono);font-size:var(--t-mono-xs);line-height:1.4;
}
.k-choice input{position:absolute;opacity:0;width:0;height:0;}

.k-box{
  flex:none;width:18px;height:18px;margin-top:.05em;
  background:var(--paper);border:var(--line);position:relative;
  transition:background .12s,box-shadow .12s;
}
/* the tick is two rules rotated into a check — drawn, never an icon font */
.k-box::after{
  content:"";position:absolute;left:4px;top:1px;width:6px;height:11px;
  border:solid var(--char);border-width:0 2.5px 2.5px 0;
  transform:rotate(45deg) scale(0);transform-origin:center;
  transition:transform .12s var(--ease-thud);
}
.k-choice input:checked + .k-box{background:var(--amber);}
.k-choice input:checked + .k-box::after{transform:rotate(45deg) scale(1);}
.k-choice input:focus-visible + .k-box{box-shadow:var(--drop-xs);}
.k-choice input:disabled + .k-box{background:var(--cream-2);opacity:.5;}
.k-choice input:disabled ~ .k-txt{opacity:.5;}

/* radio — the only round control in the system, because a radio that is
   square is indistinguishable from a checkbox */
.k-box--radio{border-radius:var(--radius-dot);}
.k-box--radio::after{
  left:3px;top:3px;width:10px;height:10px;border:none;border-radius:var(--radius-dot);
  background:var(--char);transform:scale(0);
}
.k-choice input:checked + .k-box--radio::after{transform:scale(1);}

/* switch — a sliding square inside a keylined track. Steps, never eases. */
.k-switch{
  flex:none;width:40px;height:22px;background:var(--paper);border:var(--line);
  position:relative;transition:background .12s;
}
.k-switch::after{
  content:"";position:absolute;left:2px;top:2px;width:14px;height:14px;
  background:var(--char);transition:transform .12s steps(3,end);
}
.k-choice input:checked + .k-switch{background:var(--amber);}
.k-choice input:checked + .k-switch::after{transform:translateX(18px);}
.k-choice input:focus-visible + .k-switch{box-shadow:var(--drop-xs);}

/* ==========================================================================
   TABLE
   A real data table, in the system's print language: keylined, mono, tabular
   figures. Header is a charcoal strip. Rows separate with a hairline only.
   ========================================================================== */

.k-table{
  width:100%;border-collapse:collapse;
  background:var(--paper);border:var(--line);
  font-family:var(--mono);font-size:var(--t-mono-xs);
}
.k-table thead th{
  background:var(--char);color:var(--cream);text-align:left;
  font-weight:var(--w-mono);font-size:var(--t-micro-xs);
  letter-spacing:var(--track-micro);text-transform:uppercase;
  padding:.6em .8em;white-space:nowrap;
}
.k-table tbody td{
  padding:.6em .8em;border-top:var(--line-hair);
  font-variant-numeric:tabular-nums;
}
.k-table tbody tr:hover td{background:var(--cream);}
.k-table .num{text-align:right;}
/* the row that is you */
.k-table tbody tr.you td{background:var(--amber);}
.k-table tbody tr.you:hover td{background:var(--amber);}

/* ==========================================================================
   STATUS
   A dot plus a mono word. The dot colour is the whole signal — never rely on
   the word alone, and never use an emoji.
   ========================================================================== */

.k-status{
  display:inline-flex;align-items:center;gap:.45em;
  font-family:var(--mono);font-weight:var(--w-mono);font-size:var(--t-micro-xs);
  letter-spacing:var(--track-micro);text-transform:uppercase;
}
.k-status i{
  width:9px;height:9px;flex:none;border-radius:var(--radius-dot);
  background:var(--sc,var(--char));border:1.5px solid var(--char);
}
.k-status--live i{background:var(--amber);animation:blink 1.4s steps(2) infinite;}
.k-status--ok   i{background:var(--sky);}
.k-status--warn i{background:var(--pink);}
.k-status--idle i{background:var(--cream-2);}

/* ==========================================================================
   TABS
   Keylined tabs sitting on a rule. The active one is amber and lifts, exactly
   like the chapter rail — same object, different job.
   ========================================================================== */

.k-tabs{display:flex;gap:.5rem;border-bottom:var(--line-2);padding-bottom:0;}
.k-tab{
  font-family:var(--mono);font-weight:var(--w-mono);font-size:var(--t-micro);
  letter-spacing:var(--track-mono);text-transform:uppercase;
  background:var(--paper);border:var(--line-2);border-bottom:none;
  padding:.55em .9em;cursor:pointer;opacity:.55;
  transition:opacity .16s,background .16s,transform .16s var(--ease-fill);
}
.k-tab:hover{opacity:.85;}
.k-tab[aria-selected="true"]{opacity:1;background:var(--amber);transform:translateY(-2px);}

/* ==========================================================================
   DIALOG
   The one place a blurred backdrop is allowed, matching the nav.
   ========================================================================== */

.k-scrim{
  position:fixed;inset:0;z-index:200;
  background:rgba(23,22,19,.62);backdrop-filter:blur(9px);
  display:flex;align-items:center;justify-content:center;padding:var(--gutter);
}
.k-dialog{
  background:var(--paper);border:var(--line);box-shadow:var(--drop-lg);
  width:min(100%,520px);max-height:85vh;overflow:auto;
}
.k-dialog-head{
  display:flex;align-items:center;gap:.5rem;padding:.7rem 1rem;
  border-bottom:var(--line-2);
  font-family:var(--mono);font-weight:var(--w-mono);font-size:var(--t-micro);
  letter-spacing:var(--track-micro);text-transform:uppercase;
}
.k-dialog-head i{width:var(--dot-size);height:var(--dot-size);border-radius:var(--radius-dot);background:var(--amber);}
.k-dialog-head i:nth-child(2){background:var(--pink);}
.k-dialog-head i:nth-child(3){background:var(--sky);}
.k-dialog-head .k-x{margin-left:auto;cursor:pointer;font-size:1rem;line-height:1;opacity:.6;}
.k-dialog-head .k-x:hover{opacity:1;}
.k-dialog-body{padding:1.3rem 1.4rem;}
.k-dialog-foot{
  display:flex;gap:.7rem;justify-content:flex-end;
  padding:1rem 1.4rem;border-top:var(--line-2);
}

/* ==========================================================================
   TOAST
   Slides in from the right and sits on its shadow. Ink by kind.
   ========================================================================== */

.k-toasts{
  position:fixed;right:var(--gutter);bottom:var(--gutter);z-index:210;
  display:flex;flex-direction:column;gap:.7rem;align-items:flex-end;
}
.k-toast{
  display:flex;align-items:center;gap:.7rem;
  font-family:var(--mono);font-weight:var(--w-mono);font-size:var(--t-mono-xs);
  background:var(--tc,var(--paper));color:var(--char);
  border:var(--line);box-shadow:var(--drop-sm);padding:.7em 1em;max-width:380px;
  animation:toastIn .3s var(--ease-place);
}
@keyframes toastIn{from{opacity:0;transform:translateX(30px) rotate(2deg);}to{opacity:1;transform:none;}}
.k-toast--ok{--tc:var(--sky);}
.k-toast--warn{--tc:var(--amber);}
.k-toast--err{--tc:var(--pink);}

/* ==========================================================================
   SPINNER
   Three ink bars filling in sequence — the boot screen's move, shrunk.
   It steps; it never spins, because nothing in this system rotates
   continuously.
   ========================================================================== */

.k-spinner{display:inline-flex;gap:3px;align-items:flex-end;height:14px;}
.k-spinner i{
  width:5px;height:100%;transform:scaleY(.35);transform-origin:50% 100%;
  animation:sbar .9s steps(3,end) infinite;
}
.k-spinner i:nth-child(1){background:var(--amber);animation-delay:0s;}
.k-spinner i:nth-child(2){background:var(--pink);animation-delay:.15s;}
.k-spinner i:nth-child(3){background:var(--sky);animation-delay:.3s;}
@keyframes sbar{0%,100%{transform:scaleY(.35);}50%{transform:scaleY(1);}}

/* ==========================================================================
   APP SHELL
   A charcoal rail on the left, a paper canvas on the right. The rail is the
   nav's language; the canvas is the dock's.
   ========================================================================== */

.k-app{display:grid;grid-template-columns:232px 1fr;min-height:100vh;}
.k-rail{
  background:var(--char);color:var(--cream);
  padding:1.2rem 1rem;display:flex;flex-direction:column;gap:.3rem;
  border-right:var(--line);
}
.k-rail .k-railitem{
  font-family:var(--mono);font-weight:var(--w-mono);font-size:var(--t-micro);
  letter-spacing:var(--track-mono);text-transform:uppercase;
  padding:.55em .7em;opacity:.6;cursor:pointer;text-align:left;
  transition:opacity .16s,background .16s;
}
.k-rail .k-railitem:hover{opacity:1;background:var(--char-2);}
.k-rail .k-railitem[aria-current="page"]{opacity:1;background:var(--char-2);}
.k-rail .k-railitem[aria-current="page"]::before{content:"■";color:var(--amber);margin-right:.5em;font-size:.7em;}
.k-canvas{background:var(--cream);padding:1.6rem var(--gutter);overflow:auto;}

@media(max-width:820px){
  .k-app{grid-template-columns:1fr;}
  .k-rail{flex-direction:row;overflow-x:auto;border-right:none;border-bottom:var(--line);}
}
