  :root{
    --bg: #070b14;
    --bg-1: #0c1220;
    --panel: #0f1930;
    --panel-2: #131f3d;
    --line: rgba(126,178,255,0.14);
    --line-strong: rgba(126,178,255,0.28);
    --text: #e8eefb;
    --text-dim: #8695b3;
    --text-faint: #4d5a78;

    --sala1: #33e6ff;
    --sala1-soft: rgba(51,230,255,0.14);
    --sala1-strong: rgba(51,230,255,0.55);

    --sala2: #ff4fb8;
    --sala2-soft: rgba(255,79,184,0.14);
    --sala2-strong: rgba(255,79,184,0.55);

    --warn: #ffb020;
    --danger: #ff5d5d;
    --ok: #35e08a;

    --radius: 10px;
    --font-display: ui-monospace, "SF Mono", "JetBrains Mono", "Cascadia Code", Menlo, Consolas, monospace;
    --font-body: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
  }

  *{ box-sizing: border-box; }
  html, body{ margin:0; padding:0; }
  body{
    background: var(--bg);
    color: var(--text);
    font-family: var(--font-body);
    min-height: 100vh;
    -webkit-font-smoothing: antialiased;
  }

  /* ambient grid backdrop */
  .backdrop{
    position: fixed; inset: 0; z-index: 0; pointer-events: none;
    background:
      radial-gradient(1100px 600px at 12% -10%, rgba(51,230,255,0.10), transparent 60%),
      radial-gradient(900px 500px at 95% 10%, rgba(255,79,184,0.08), transparent 55%),
      linear-gradient(var(--bg-1), var(--bg));
  }
  .backdrop::before{
    content:"";
    position:absolute; inset:0;
    background-image:
      linear-gradient(var(--line) 1px, transparent 1px),
      linear-gradient(90deg, var(--line) 1px, transparent 1px);
    background-size: 42px 42px;
    opacity: 0.35;
    mask-image: radial-gradient(1000px 600px at 50% 0%, black, transparent 75%);
  }

  .app{ position:relative; z-index:1; max-width:1180px; margin:0 auto; padding: 22px 18px 60px; }

  /* header */
  .hud{
    display:flex; align-items:flex-start; justify-content:space-between; gap:16px; flex-wrap:wrap;
    padding-bottom:16px; margin-bottom:18px; border-bottom:1px solid var(--line);
  }
  .brand{ display:flex; align-items:center; gap:12px; }
  .brand-mark{
    width:38px; height:38px; border-radius:8px; flex:none;
    background: conic-gradient(from 220deg, var(--sala1), var(--sala2), var(--sala1));
    display:flex; align-items:center; justify-content:center;
    box-shadow: 0 0 22px rgba(51,230,255,0.35);
  }
  .brand-mark span{
    width:28px; height:28px; border-radius:6px; background: var(--bg);
    display:flex; align-items:center; justify-content:center;
    font-family: var(--font-display); font-size:11px; font-weight:700; letter-spacing:0.02em;
    color: var(--text);
  }
  .brand h1{
    font-family: var(--font-display); font-size:16px; letter-spacing:0.14em; text-transform:uppercase;
    margin:0; font-weight:600;
  }
  .brand p{
    margin:2px 0 0; font-size:12px; color: var(--text-dim); letter-spacing:0.02em;
    display:flex; align-items:center; gap:7px;
  }
  .sync-dot{
    width:7px; height:7px; border-radius:50%; background: var(--ok); flex:none;
    box-shadow: 0 0 6px var(--ok);
  }
  .sync-dot.syncing{ background: var(--warn); box-shadow:0 0 6px var(--warn); animation: pulse 1s ease-in-out infinite; }
  .sync-dot.offline{ background: var(--danger); box-shadow:0 0 6px var(--danger); animation:none; }
  @keyframes pulse{ 0%,100%{ opacity:1; } 50%{ opacity:0.35; } }
  @media (prefers-reduced-motion: reduce){ .sync-dot.syncing{ animation:none; } }

  .clock{
    font-family: var(--font-display); text-align:right; font-variant-numeric: tabular-nums;
  }
  .clock .time{ font-size:20px; color: var(--sala1); text-shadow: 0 0 16px rgba(51,230,255,0.45); letter-spacing: 0.04em; }
  .clock .date{ font-size:11px; color: var(--text-dim); text-transform:uppercase; letter-spacing:0.1em; margin-top:2px; }

  /* connection banner */
  .banner{
    display:none; align-items:center; gap:10px; background: rgba(255,93,93,0.1);
    border:1px solid var(--danger); color: var(--danger); border-radius: var(--radius);
    padding:10px 14px; font-size:13px; margin-bottom:16px;
  }
  .banner.show{ display:flex; }

  /* status row */
  .status-row{
    display:flex; gap:12px; flex-wrap:wrap; margin-bottom:18px;
  }
  .status-chip{
    flex:1; min-width:220px;
    display:flex; align-items:center; gap:10px;
    background: var(--panel); border:1px solid var(--line); border-radius: var(--radius);
    padding:10px 14px;
  }
  .status-chip .dot{
    width:9px; height:9px; border-radius:50%; flex:none;
  }
  .status-chip.s1 .dot{ background: var(--sala1); box-shadow:0 0 10px var(--sala1-strong); }
  .status-chip.s2 .dot{ background: var(--sala2); box-shadow:0 0 10px var(--sala2-strong); }
  .status-chip .label{ font-family: var(--font-display); font-size:11px; letter-spacing:0.08em; text-transform:uppercase; color:var(--text-dim); }
  .status-chip .value{ font-size:13px; margin-left:auto; text-align:right; }
  .status-chip .value b{ color: var(--text); font-weight:600; }
  .status-chip .value.free{ color: var(--ok); }
  .status-chip .value.busy{ color: var(--warn); }

  /* week nav */
  .week-nav{
    display:flex; align-items:center; justify-content:space-between; gap:10px; margin-bottom:14px;
    flex-wrap: wrap;
  }
  .week-nav .range{
    font-family: var(--font-display); font-size:13px; letter-spacing:0.06em; color: var(--text);
    text-transform:uppercase;
  }
  .nav-controls{ display:flex; gap:8px; }
  .btn{
    font-family: var(--font-body); font-size:13px; font-weight:600;
    background: var(--panel); color: var(--text); border:1px solid var(--line-strong);
    border-radius:8px; padding:9px 14px; cursor:pointer; transition: all .15s ease;
  }
  .btn:hover{ border-color: var(--sala1); box-shadow: 0 0 0 1px var(--sala1) inset; }
  .btn:focus-visible{ outline:2px solid var(--sala1); outline-offset:2px; }
  .btn.ghost{ background:transparent; }
  .btn.primary{
    background: linear-gradient(135deg, rgba(51,230,255,0.18), rgba(255,79,184,0.14));
    border-color: var(--sala1-strong);
  }
  .btn.danger{ border-color: var(--danger); color: var(--danger); background:transparent; }
  .btn.danger:hover{ box-shadow: 0 0 0 1px var(--danger) inset; }
  .btn:disabled{ opacity:0.35; cursor:not-allowed; }

  /* legend */
  .legend{ display:flex; gap:16px; flex-wrap:wrap; margin-bottom:14px; }
  .legend-item{ display:flex; align-items:center; gap:7px; font-size:12px; color: var(--text-dim); }
  .swatch{ width:13px; height:13px; border-radius:4px; flex:none; border:1px solid var(--line-strong); }
  .swatch.free{ background: var(--panel); }
  .swatch.s1{ background: var(--sala1-soft); border-color: var(--sala1-strong); }
  .swatch.s2{ background: var(--sala2-soft); border-color: var(--sala2-strong); }

  /* schedule */
  .schedule-wrap{
    position:relative;
    overflow-x:auto; border:1px solid var(--line); border-radius: var(--radius);
    background: var(--panel);
  }
  /* `fixed` es lo que hace que las columnas midan siempre lo mismo. Con el
     layout automático el navegador reparte el ancho según el contenido, así que
     un nombre largo o un motivo de 80 caracteres ensanchaban su columna y
     encogían las demás: la cuadrícula cambiaba de forma según quién reservara.
     Fijo, los anchos salen sólo de estas reglas y el texto que no entra se
     recorta con puntos suspensivos, como ya hacían .who y .title. */
  table.schedule{ border-collapse: collapse; width:100%; min-width:760px; table-layout: fixed; }
  table.schedule th, table.schedule td{ border:1px solid var(--line); }
  thead th{
    position: sticky; top:0; background: var(--panel-2); z-index:2;
    padding:8px 4px; font-family: var(--font-display); font-weight:600;
  }
  thead th.time-head{ background: var(--panel-2); width:76px; }
  /* Las cinco columnas de día se reparten en partes iguales lo que sobra. Se
     declara en el encabezado porque con table-layout fijo mandan la primera
     fila y el <col>, no las celdas del cuerpo. */
  thead th.day-head{ width: calc((100% - 76px) / 5); }
  .day-head{ text-align:center; padding-bottom:2px; }
  .day-head .dname{ font-size:11px; letter-spacing:0.1em; text-transform:uppercase; color: var(--text); }
  .day-head .ddate{ font-size:10px; color: var(--text-dim); font-weight:400; text-transform:none; letter-spacing:0.02em; }
  .room-sub{ display:flex; }
  .room-label{
    flex:1; text-align:center; font-size:9px; letter-spacing:0.12em; padding:5px 2px;
    text-transform:uppercase; font-weight:700;
  }
  .room-label.s1{ color: var(--sala1); }
  .room-label.s2{ color: var(--sala2); }

  .time-cell{
    font-family: var(--font-display); font-size:11px; color: var(--text-dim);
    text-align:center; white-space:nowrap; padding:0 6px; font-variant-numeric: tabular-nums;
    background: var(--panel-2);
  }

  td.slot-cell{ padding:3px; vertical-align:middle; }
  .slot{
    width:100%; min-height:46px; border-radius:7px; border:1px dashed var(--line-strong);
    background: transparent; color: var(--text-dim); cursor:pointer;
    font-family: var(--font-body); font-size:11px; padding:5px 6px; text-align:left;
    transition: transform .12s ease, box-shadow .12s ease, border-color .12s ease, background .12s ease;
    display:flex; flex-direction:column; gap:1px; justify-content:center;
    /* `min-width:0` deja que los hijos se recorten en vez de empujar hacia
       afuera: sin esto un texto largo desborda la celda de ancho fijo. */
    min-width:0; overflow:hidden;
  }
  /* Cualquier línea del slot se recorta antes que ensanchar nada. */
  .slot > span{ overflow:hidden; text-overflow:ellipsis; white-space:nowrap; min-width:0; }
  /* Una reunión de varias horas ocupa una celda con rowspan. `height:100%` no
     sirve ahí: el td no tiene altura propia —se la dan las filas que abarca— y
     el porcentaje se queda sin contra qué resolver, así que el botón volvía a
     su min-height y el fondo terminaba antes que el bloque. Posicionándolo
     contra la celda sí cubre las tres filas enteras. */
  td.slot-cell.multi-cell{ position:relative; }
  .slot.multi{ position:absolute; top:3px; right:3px; bottom:3px; left:3px; width:auto; height:auto; }
  .slot:hover:not(:disabled){ transform: translateY(-1px); }
  .slot:focus-visible{ outline:2px solid var(--sala1); outline-offset:1px; }
  .slot.free.s1:hover:not(:disabled){ border-color: var(--sala1); box-shadow: 0 0 12px rgba(51,230,255,0.25); background: rgba(51,230,255,0.05); }
  .slot.free.s2:hover:not(:disabled){ border-color: var(--sala2); box-shadow: 0 0 12px rgba(255,79,184,0.25); background: rgba(255,79,184,0.05); }
  .slot.free .plus{ opacity:0; font-size:14px; }
  .slot.free:hover:not(:disabled) .plus{ opacity:0.8; }

  @media (hover: none){
    .slot.free .plus{ opacity:0.5; }
    .slot:hover:not(:disabled){ transform:none; }
  }

  .slot.booked{ border-style: solid; cursor:pointer; }
  .slot.booked.s1{ background: var(--sala1-soft); border-color: var(--sala1-strong); }
  .slot.booked.s2{ background: var(--sala2-soft); border-color: var(--sala2-strong); }
  .slot.booked .who{ color: var(--text); font-weight:700; font-size:11px; overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
  .slot.booked .title{ color: var(--text-dim); font-size:10px; overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
  .slot.booked .tag{ font-family: var(--font-display); font-size:8px; letter-spacing:0.08em; text-transform:uppercase; }
  .slot.booked.s1 .tag{ color: var(--sala1); }
  .slot.booked.s2 .tag{ color: var(--sala2); }

  .slot.past{ opacity:0.32; cursor:not-allowed; border-style:solid; border-color: var(--text-faint); }
  /* Una reserva pasada sigue siendo el historial: se atenúa para que no compita
     con lo reservable, pero tiene que poder leerse quién y de qué fue. El hueco
     libre que ya pasó no aporta nada, así que ese sí queda apagado. */
  .slot.booked.past{ opacity:0.8; }
  .slot.past .who{ color: var(--text-dim); }
  .slot.past .title{ color: var(--text-faint); }
  .slot:disabled{ cursor:not-allowed; opacity:0.5; }

  /* Arrastre para reservar varias horas seguidas.
     `.selecting` es el bloque que quedaría reservado si soltás el mouse acá. */
  .slot.selecting{ border-style:solid; transform:none; }
  .slot.selecting.s1{ background: var(--sala1-soft); border-color: var(--sala1); }
  .slot.selecting.s2{ background: var(--sala2-soft); border-color: var(--sala2); }
  .slot.selecting .plus{ opacity:0.9; }
  /* Mientras se arrastra no queremos que el navegador seleccione texto ni que
     el hover levante las celdas: el bloque tiene que leerse como una pieza. */
  .schedule.dragging{ user-select:none; -webkit-user-select:none; }
  .schedule.dragging .slot:hover:not(:disabled){ transform:none; }

  /* Duración, en el modal de reserva */
  .dur-row{ display:flex; flex-wrap:wrap; gap:6px; margin-top:4px; }
  .dur-chip{
    font-family: var(--font-display); font-size:11px; letter-spacing:0.04em;
    padding:6px 12px; border-radius:999px; cursor:pointer;
    border:1px solid var(--line-strong); background:transparent; color: var(--text-dim);
    transition: border-color .12s ease, color .12s ease, background .12s ease;
  }
  .dur-chip:hover:not(:disabled){ color: var(--text); border-color: var(--text-dim); }
  .dur-chip[aria-pressed="true"]{ background: var(--sala1-soft); border-color: var(--sala1); color: var(--text); }
  .dur-chip:disabled{ opacity:0.3; cursor:not-allowed; }

  /* footer note */
  .footnote{
    margin-top:20px; font-size:12px; color: var(--text-faint); line-height:1.6; max-width:65ch;
  }
  .footnote b{ color: var(--text-dim); }

  /* modal */
  .overlay{
    position:fixed; inset:0; background: rgba(4,7,14,0.72); backdrop-filter: blur(2px);
    display:flex; align-items:center; justify-content:center; padding:20px; z-index:50;
  }
  .overlay[hidden]{ display:none; }
  .modal{
    width:100%; max-width:420px; background: var(--panel-2); border:1px solid var(--line-strong);
    border-radius:12px; padding:22px; box-shadow: 0 20px 60px rgba(0,0,0,0.5);
  }
  .modal h2{
    margin:0 0 4px; font-family: var(--font-display); font-size:14px; letter-spacing:0.08em; text-transform:uppercase;
  }
  .modal .sub{ font-size:12px; color: var(--text-dim); margin:0 0 18px; }
  .field{ margin-bottom:14px; }
  .field label{ display:block; font-size:12px; color: var(--text-dim); margin-bottom:6px; }
  .field input{
    width:100%; background: var(--bg); border:1px solid var(--line-strong); border-radius:7px;
    padding:10px 12px; color: var(--text); font-size:14px; font-family: var(--font-body);
  }
  .field input:focus-visible{ outline:2px solid var(--sala1); outline-offset:1px; }
  .field .err{ color: var(--danger); font-size:11px; margin-top:5px; display:none; }
  .field.invalid input{ border-color: var(--danger); }
  .field.invalid .err{ display:block; }
  /* ojito para ver la contraseña; el wrapper lo arma el JS */
  .pw-wrap{ position:relative; display:block; }
  .pw-wrap input{ padding-right:42px; }
  .pw-eye{
    position:absolute; right:4px; top:50%; transform:translateY(-50%);
    background:none; border:0; padding:7px; cursor:pointer; line-height:0;
    color: var(--text-dim); border-radius:6px;
  }
  .pw-eye:hover{ color: var(--sala1); }
  .pw-eye:focus-visible{ outline:2px solid var(--sala1); outline-offset:1px; }
  .pw-eye svg{ width:18px; height:18px; display:block; }
  .pw-eye .eye-off{ display:none; }
  .pw-eye.is-on .eye-on{ display:none; }
  .pw-eye.is-on .eye-off{ display:block; }
  .modal-actions{ display:flex; gap:10px; justify-content:flex-end; margin-top:18px; }

  .detail-row{ display:flex; justify-content:space-between; font-size:13px; padding:7px 0; border-bottom:1px solid var(--line); }
  .detail-row:last-of-type{ border-bottom:none; }
  .detail-row span:first-child{ color: var(--text-dim); }
  .detail-row span:last-child{ font-weight:600; }

  /* toasts */
  .toast-region{ position:fixed; right:18px; bottom:18px; display:flex; flex-direction:column; gap:8px; z-index:60; }
  .toast{
    background: var(--panel-2); border:1px solid var(--sala1-strong); border-radius:9px;
    padding:11px 16px; font-size:13px; color: var(--text); box-shadow:0 8px 24px rgba(0,0,0,0.4);
    animation: toast-in .18s ease;
  }
  .toast.error{ border-color: var(--danger); }
  @keyframes toast-in{ from{ opacity:0; transform: translateY(6px); } to{ opacity:1; transform:none; } }

  .visually-hidden{ position:absolute; width:1px; height:1px; overflow:hidden; clip:rect(0,0,0,0); white-space:nowrap; }


  /* Tutorial guiado. El "!" del encabezado lo abre; el foco se dibuja como un
     recorte sobre el elemento del paso (box-shadow gigante), así no hay que
     clonar nada ni tocar el z-index de la app. */
  .help-btn{
    width:30px; height:30px; flex:none; border-radius:50%;
    background: var(--panel); border:1px solid var(--line-strong); color: var(--sala1);
    font-family: var(--font-display); font-size:15px; font-weight:700; line-height:1;
    cursor:pointer; display:flex; align-items:center; justify-content:center;
  }
  .help-btn:hover{ border-color: var(--sala1); }
  .help-btn:focus-visible{ outline:2px solid var(--sala1); outline-offset:2px; }

  /* El velo va transparente a propósito: el oscurecimiento lo pone la sombra
     del recorte. Si los dos tiñeran, se sumarían y la pantalla quedaría negra. */
  .tour-scrim{ position:fixed; inset:0; z-index:70; background: transparent; }
  .tour-scrim.solid{ background: rgba(4,7,14,0.5); }
  .tour-scrim[hidden]{ display:none; }
  .tour-spot{
    position:fixed; z-index:71; border-radius:10px; pointer-events:none;
    border:2px solid var(--sala1); box-shadow: 0 0 0 9999px rgba(4,7,14,0.5);
    transition: top .18s ease, left .18s ease, width .18s ease, height .18s ease;
  }
  .tour-spot[hidden]{ display:none; }

  /* Demostración del arrastre: el bloque crece sobre las celdas reales y el
     puntero lo acompaña, en bucle mientras el paso está a la vista. */
  .drag-demo{
    position:fixed; z-index:73; pointer-events:none; border-radius:8px;
    background: linear-gradient(135deg, rgba(51,230,255,0.28), rgba(51,230,255,0.14));
    border:2px solid var(--sala1);
  }
  .drag-demo[hidden], .drag-pointer[hidden]{ display:none; }
  .drag-pointer{
    position:fixed; z-index:74; pointer-events:none;
    width:16px; height:16px; margin:-8px 0 0 -8px; border-radius:50%;
    background: rgba(51,230,255,0.9); box-shadow: 0 0 0 6px rgba(51,230,255,0.22);
  }
  .tour-card{
    position:fixed; z-index:72; width:min(340px, calc(100vw - 32px));
    background: var(--panel-2); border:1px solid var(--line-strong); border-radius:12px;
    padding:18px; box-shadow: 0 20px 60px rgba(0,0,0,0.55);
  }
  .tour-card[hidden]{ display:none; }
  .tour-card h2{
    margin:0 0 6px; font-family: var(--font-display); font-size:13px;
    letter-spacing:0.08em; text-transform:uppercase;
  }
  .tour-card p{ margin:0; font-size:13px; line-height:1.6; color: var(--text-dim); }
  .tour-card p b{ color: var(--text); font-weight:600; }
  .tour-foot{ display:flex; align-items:center; justify-content:space-between; gap:10px; margin-top:16px; }
  .tour-dots{ display:flex; gap:5px; }
  .tour-dots i{ width:6px; height:6px; border-radius:50%; background: var(--line-strong); display:block; }
  .tour-dots i.on{ background: var(--sala1); }
  .tour-foot .btns{ display:flex; gap:8px; }
  @media (prefers-reduced-motion: reduce){ .tour-spot{ transition:none; } }

  @media (max-width: 640px){
    .app{ padding: 14px 10px 44px; }

    /* El encabezado se queda en una fila: apilado, el reloj empujaba la
       cuadrícula fuera de la primera pantalla. */
    .hud{ align-items:center; gap:10px; padding-bottom:12px; margin-bottom:14px; }
    .brand{ gap:9px; min-width:0; }
    .brand-mark{ width:30px; height:30px; }
    .brand-mark span{ width:22px; height:22px; font-size:9px; }
    .brand h1{ font-size:13px; letter-spacing:0.1em; }
    .brand p{ font-size:10px; gap:5px; }
    .clock{ text-align:right; margin-left:auto; }
    .clock .time{ font-size:15px; }
    .clock .date{ display:none; }
    .help-btn{ width:34px; height:34px; font-size:17px; }

    .status-row{ gap:8px; margin-bottom:14px; }
    .status-chip{ min-width:0; flex:1 1 100%; padding:8px 11px; }
    .status-chip .value{ font-size:12px; }

    /* Rango de fechas arriba, botones abajo repartidos a lo ancho: son los
       únicos objetivos táctiles del bloque. */
    .week-nav{ gap:8px; }
    .week-nav .range{ order:-1; flex:1 1 100%; font-size:12px; }
    .nav-controls{ width:100%; }
    .nav-controls .btn{ flex:1; padding:10px 6px; font-size:12px; }

    .legend{ gap:10px; margin-bottom:10px; font-size:11px; }
    .legend-item{ font-size:11px; }

    /* La cuadrícula sigue desplazándose de lado, pero más angosta y con la
       columna de horas fija: sin eso, al correrla se pierde a qué hora
       corresponde cada fila, que era lo peor de usarla en el teléfono. */
    table.schedule{ min-width:540px; }
    thead th{ padding:6px 3px; }
    thead th.time-head{ width:46px; }
    /* La columna de horas se angosta acá, así que el reparto de los días se
       recalcula sobre lo que queda. */
    thead th.day-head{ width: calc((100% - 46px) / 5); }
    .day-head .dname{ font-size:10px; letter-spacing:0.06em; }
    .day-head .ddate{ font-size:9px; }
    .room-label{ font-size:8px; letter-spacing:0.06em; padding:4px 1px; }

    .time-cell, thead th.time-head{
      position:sticky; left:0; z-index:3; padding:0 3px; font-size:10px;
      box-shadow: 1px 0 0 var(--line);
    }
    thead th.time-head{ z-index:4; }

    td.slot-cell{ padding:2px; }
    /* El bloque va posicionado contra la celda, así que sigue al padding de acá. */
    .slot.multi{ top:2px; right:2px; bottom:2px; left:2px; }
    .slot{ min-height:40px; padding:4px; font-size:10px; border-radius:6px; }
    .slot.booked .who{ font-size:10px; }
    .slot.booked .title{ font-size:9px; }
    .slot.booked .tag{ font-size:7px; }

    .footnote{ font-size:11px; }

    /* La tarjeta del tutorial, a lo ancho y abajo: centrada tapaba justo el
       elemento que está señalando. */
    .tour-card{
      width:auto; left:12px !important; right:12px;
      top:auto !important; bottom:12px;
    }
    .tour-card p{ font-size:12px; }
  }
