/* ============================================================================
   TradeYoke · Scheduling board + domain detail panels
   ----------------------------------------------------------------------------
   Global (non-scoped) classes shared by the board (TradeYoke.Modules.Shared) and
   the per-domain detail panels (each TradeYoke.Domains.* RCL). Loaded once by
   SchedulePage via <HeadContent>.

   THEME-AWARE: every colour is var(--ty-*, <vanilla-fallback>). With no active
   theme ("None") the fallbacks give plain, basic styling; under a theme (Trusty
   etc.) the --ty-* tokens light it up. Per-item colour comes from data-module on
   the element, which a theme re-points --ty-color-primary within.
   ============================================================================ */

/* ---- Glyph system: mask-based so the icon takes the element's `color` ------- */
.ty-glyph {
    display: inline-block;
    width: 1em;
    height: 1em;
    flex: none;
    background-color: currentColor;
    -webkit-mask: var(--g) center / contain no-repeat;
    mask: var(--g) center / contain no-repeat;
    vertical-align: -0.125em;
}
.ty-glyph-window       { --g: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='none' stroke='black' stroke-width='1.3' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M2.5 2.5h11v11h-11z M8 2.5v11 M2.5 8h11'/%3E%3C/svg%3E"); }
.ty-glyph-leaf         { --g: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='none' stroke='black' stroke-width='1.3' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M8 13v-4 M8 9a3.2 3.2 0 1 0 0-6.4 3.2 3.2 0 0 0 0 6.4z'/%3E%3C/svg%3E"); }
.ty-glyph-construction { --g: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='none' stroke='black' stroke-width='1.3' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M2 4h12 M2 8h12 M2 12h12 M7 4v4 M11 4v4 M4.5 8v4 M9 8v4'/%3E%3C/svg%3E"); }
.ty-glyph-bolt         { --g: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='none' stroke='black' stroke-width='1.3' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M9 2L4 9h3l-.7 5 5.7-7H8.3z'/%3E%3C/svg%3E"); }
.ty-glyph-wrench       { --g: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='none' stroke='black' stroke-width='1.3' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M10.6 2.2a3 3 0 0 0-3.9 3.9l-4.3 4.3a1.3 1.3 0 0 0 1.8 1.8l4.3-4.3a3 3 0 0 0 3.9-3.9l-2 2-1.6-.4-.4-1.6z'/%3E%3C/svg%3E"); }
.ty-glyph-sun          { --g: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='none' stroke='black' stroke-width='1.3' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M8 5.5a2.5 2.5 0 1 0 0 5 2.5 2.5 0 0 0 0-5z M8 1.5v1.6 M8 12.9v1.6 M1.5 8h1.6 M12.9 8h1.6 M3.6 3.6l1.1 1.1 M11.3 11.3l1.1 1.1 M12.4 3.6l-1.1 1.1 M4.7 11.3l-1.1 1.1'/%3E%3C/svg%3E"); }
.ty-glyph-check        { --g: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='none' stroke='black' stroke-width='1.5' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M3.5 8.5l3 3 6-6'/%3E%3C/svg%3E"); }
.ty-glyph-clock        { --g: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='none' stroke='black' stroke-width='1.3' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M8 3.2a4.8 4.8 0 1 0 0 9.6 4.8 4.8 0 0 0 0-9.6z M8 5.5V8l2 1.4'/%3E%3C/svg%3E"); }
.ty-glyph-calendar     { --g: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='none' stroke='black' stroke-width='1.3' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M3 4.5h10v8.5H3z M3 7h10 M6 2.8v2 M10 2.8v2'/%3E%3C/svg%3E"); }
.ty-glyph-geo          { --g: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='none' stroke='black' stroke-width='1.3' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M8 14s3.6-4 3.6-7.2A3.6 3.6 0 1 0 4.4 6.8C4.4 10 8 14 8 14z M8 5.6a1.4 1.4 0 1 0 0 2.8 1.4 1.4 0 0 0 0-2.8z'/%3E%3C/svg%3E"); }
.ty-glyph-chevron-left { --g: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='none' stroke='black' stroke-width='1.5' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M10 3.5L5.5 8l4.5 4.5'/%3E%3C/svg%3E"); }
.ty-glyph-chevron-right{ --g: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='none' stroke='black' stroke-width='1.5' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M6 3.5L10.5 8 6 12.5'/%3E%3C/svg%3E"); }
.ty-glyph-chevron-up   { --g: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='none' stroke='black' stroke-width='1.5' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M3.5 10L8 5.5l4.5 4.5'/%3E%3C/svg%3E"); }
.ty-glyph-chevron-down { --g: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='none' stroke='black' stroke-width='1.5' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M3.5 6L8 10.5 12.5 6'/%3E%3C/svg%3E"); }
.ty-glyph-close        { --g: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='none' stroke='black' stroke-width='1.5' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M4 4l8 8 M12 4l-8 8'/%3E%3C/svg%3E"); }
.ty-glyph-plus         { --g: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='none' stroke='black' stroke-width='1.5' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M8 3.2v9.6 M3.2 8h9.6'/%3E%3C/svg%3E"); }
.ty-glyph-skip         { --g: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='none' stroke='black' stroke-width='1.4' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M8 3.2a4.8 4.8 0 1 0 0 9.6 4.8 4.8 0 0 0 0-9.6z M4.7 4.7l6.6 6.6'/%3E%3C/svg%3E"); }
.ty-glyph-replan       { --g: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='none' stroke='black' stroke-width='1.4' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M12.4 5.4A4.9 4.9 0 1 0 12.9 8.4 M12.9 2.6v2.9H10'/%3E%3C/svg%3E"); }

/* Map a domain module key → its glyph, so any element with data-module gets the icon. */
[data-module="window-cleaning"] .ty-domain-glyph { --g: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='none' stroke='black' stroke-width='1.3' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M8 2.3c-2.4 3-3.7 5-3.7 7.1a3.7 3.7 0 1 0 7.4 0C11.7 7.3 10.4 5.3 8 2.3z'/%3E%3C/svg%3E"); }
[data-module="gardening"]       .ty-domain-glyph { --g: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='none' stroke='black' stroke-width='1.3' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M8 2.3L5 6.5h1.6L4.5 9.8h7L9.4 6.5H11z M8 9.8v3.4'/%3E%3C/svg%3E"); }
[data-module="scaffolding"]     .ty-domain-glyph { --g: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='none' stroke='black' stroke-width='1.3' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M2 4h12 M2 8h12 M2 12h12 M7 4v4 M11 4v4 M4.5 8v4 M9 8v4'/%3E%3C/svg%3E"); }
[data-module="electrician"]     .ty-domain-glyph { --g: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='none' stroke='black' stroke-width='1.3' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M9 2L4 9h3l-.7 5 5.7-7H8.3z'/%3E%3C/svg%3E"); }
[data-module="plumber"]         .ty-domain-glyph { --g: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='none' stroke='black' stroke-width='1.3' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M10.6 2.2a3 3 0 0 0-3.9 3.9l-4.3 4.3a1.3 1.3 0 0 0 1.8 1.8l4.3-4.3a3 3 0 0 0 3.9-3.9l-2 2-1.6-.4-.4-1.6z'/%3E%3C/svg%3E"); }
[data-module="solar-installer"] .ty-domain-glyph { --g: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='none' stroke='black' stroke-width='1.3' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M8 5.5a2.5 2.5 0 1 0 0 5 2.5 2.5 0 0 0 0-5z M8 1.5v1.6 M8 12.9v1.6 M1.5 8h1.6 M12.9 8h1.6 M3.6 3.6l1.1 1.1 M11.3 11.3l1.1 1.1 M12.4 3.6l-1.1 1.1 M4.7 11.3l-1.1 1.1'/%3E%3C/svg%3E"); }

/* ---- Board shell ----------------------------------------------------------- */
.ty-sched {
    font-family: var(--ty-font-base, 'Helvetica Neue', Helvetica, Arial, sans-serif);
    color: var(--ty-color-text, #1c2128);
}
.ty-sched-head {
    display: flex;
    align-items: center;
    gap: 12px;
    flex-wrap: wrap;
    margin-bottom: 16px;
}
.ty-sched-title {
    font-size: 20px;
    font-weight: var(--ty-weight-bold, 700);
    letter-spacing: -0.01em;
    margin: 0;
}
.ty-sched-spacer { flex: 1; }

/* Segmented control (Day / Week / Month) */
/* .ty-seg (and its --views / --sub / --pin variants) is styled app-wide in app.css. */

/* A secondary segment that QUALIFIES the chosen view (how many months) rather than choosing one — smaller
   and quieter, so the eye still reads Day/Week/Month/List as the primary switch. */

/* "Months shown  [1][2][3]" — a bare 1/2/3 beside the view switch would read as four more views, so the
   control carries its own visible label and sits in a tinted well tied to the accent colour: obviously an
   option OF the month view, obviously not one of the views. */
.ty-monthspan {
    display: inline-flex;
    align-items: center;
    gap: 8px;
    padding: 3px 8px 3px 10px;
    border-radius: var(--ty-radius-control, 8px);
    border: 1px dashed color-mix(in srgb, var(--ty-color-primary, #1b6ec2) 35%, transparent);
    background: color-mix(in srgb, var(--ty-color-primary, #1b6ec2) 6%, transparent);
}
.ty-monthspan-label {
    font: 600 11px var(--ty-font-base, inherit);
    letter-spacing: .04em;
    text-transform: uppercase;
    color: var(--ty-color-primary, #1b6ec2);
    white-space: nowrap;
}

/* Date navigator */
.ty-datenav {
    display: inline-flex;
    align-items: center;
    gap: 4px;
    border: 1px solid var(--ty-color-border, #e2e6ea);
    border-radius: var(--ty-radius-control, 8px);
    padding: 3px 5px;
    background: var(--ty-color-surface, #fff);
}
.ty-datenav-label { font: 600 12.5px var(--ty-font-base, inherit); padding: 0 6px; min-width: 8ch; text-align: center; }
.ty-iconbtn {
    appearance: none;
    border: 0;
    background: transparent;
    color: var(--ty-color-text-muted, #57606a);
    cursor: pointer;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 26px;
    height: 26px;
    border-radius: 6px;
    font-size: 14px;
}
.ty-iconbtn:hover { background: var(--ty-color-surface-3, #eef1f4); }
.ty-today-btn {
    appearance: none;
    border: 1px solid var(--ty-color-border, #e2e6ea);
    background: var(--ty-color-surface, #fff);
    border-radius: var(--ty-radius-control, 8px);
    font: 600 12px var(--ty-font-base, inherit);
    color: var(--ty-color-text, #1c2128);
    padding: 6px 11px;
    cursor: pointer;
}

/* Trade filter chips */
.ty-chip {
    appearance: none;
    display: inline-flex;
    align-items: center;
    gap: 6px;
    font: 600 12px var(--ty-font-base, inherit);
    padding: 6px 11px;
    border-radius: var(--ty-radius-pill, 999px);
    border: 1px solid var(--ty-color-border, #d8dee6);
    color: var(--ty-color-text-muted, #57606a);
    background: var(--ty-color-surface, #fff);
    cursor: pointer;
}
.ty-chip .ty-swatch { width: 9px; height: 9px; border-radius: 3px; background: var(--ty-color-primary, #1b6ec2); }
.ty-chip.on { background: var(--ty-color-primary, #1b6ec2); border-color: var(--ty-color-primary, #1b6ec2); color: var(--ty-color-primary-contrast, #fff); }
.ty-chip.on .ty-swatch { background: rgba(255,255,255,.8); }
/* A job-type chip: the glyph IS the label, so the chip squares up around it and the icon carries the
   trade's own colour — the coloured dot said "this trade has a colour", the icon says WHICH trade. Picked,
   the chip fills with that trade's colour rather than the generic primary, so the board, the agenda and
   the header all agree on what "Gardening is selected" looks like. */
.ty-chip--trade { padding: 6px 9px; }
.ty-chip-ico { font-size: 14px; line-height: 1; color: var(--dom, var(--ty-color-primary, #1b6ec2)); }
.ty-chip--trade.on { background: var(--dom, var(--ty-color-primary, #1b6ec2)); border-color: var(--dom, var(--ty-color-primary, #1b6ec2)); }
.ty-chip--trade.on .ty-chip-ico { color: var(--ty-color-primary-contrast, #fff); }

.ty-btn-primary {
    appearance: none;
    display: inline-flex;
    align-items: center;
    gap: 7px;
    border: 0;
    font: 600 12.5px var(--ty-font-base, inherit);
    color: var(--ty-color-primary-contrast, #fff);
    background: var(--ty-color-primary, #1b6ec2);
    padding: 8px 14px;
    border-radius: var(--ty-radius-control, 8px);
    cursor: pointer;
}

/* Subtle "Take a tour" affordance — a ghost-style link-button so it doesn't compete with New/filters. */
.ty-tour-replay-btn {
    appearance: none;
    display: inline-flex;
    align-items: center;
    gap: 5px;
    border: 0;
    background: transparent;
    font: 600 12px var(--ty-font-base, inherit);
    color: var(--ty-color-text-subtle, #8a95a1);
    padding: 6px 8px;
    border-radius: var(--ty-radius-control, 8px);
    cursor: pointer;
}
.ty-tour-replay-btn:hover { color: var(--ty-color-primary, #1b6ec2); background: var(--ty-color-surface-3, #eef1f4); }

/* ---- Job card (day agenda) ------------------------------------------------- */
.ty-agenda { display: flex; flex-direction: column; gap: 12px; }
.ty-agenda-empty {
    color: var(--ty-color-text-subtle, #8a95a1);
    font-size: 13px;
    padding: 28px 4px;
    text-align: center;
    border: 1px dashed var(--ty-color-border, #e2e6ea);
    border-radius: var(--ty-radius-card, 12px);
}
.ty-agenda-row { display: flex; gap: 13px; align-items: stretch; }
.ty-agenda-time {
    width: 46px;
    flex: none;
    font: 600 12px var(--ty-font-base, inherit);
    color: var(--ty-color-text-muted, #57606a);
    padding-top: 12px;
}
.ty-jobcard {
    flex: 1;
    min-width: 0;
    display: flex;
    text-align: left;
    background: var(--ty-color-surface, #fff);
    border: 1px solid var(--ty-color-border, #e2e6ea);
    border-left: 4px solid var(--ty-color-primary, #1b6ec2);
    border-radius: var(--ty-radius-card, 12px);
    overflow: hidden;
    padding: 0;
    /* No cursor here: the card is two zones now — the grip says "grab", the open-button says "click". A
       cursor on the container would contradict whichever one you are actually over. */
    transition: box-shadow var(--ty-motion-micro, 120ms) ease, transform var(--ty-motion-micro, 120ms) ease;
}

/* The clickable half: everything that is not the grip opens the job. Reset to inherit the card's own type
   and colour so splitting the markup changed nothing visible. */
.ty-jobcard-open {
    appearance: none;
    flex: 1;
    min-width: 0;
    display: block;
    text-align: left;
    background: none;
    border: 0;
    padding: 0;
    font: inherit;
    color: inherit;
    cursor: pointer;
}
.ty-jobcard:hover { box-shadow: var(--ty-shadow-md, 0 4px 14px -8px rgba(0,0,0,.35)); }
.ty-jobcard.selected { box-shadow: 0 0 0 2px var(--ty-color-primary, #1b6ec2); }
.ty-jobcard-body { padding: 11px 13px; flex: 1; min-width: 0; }
.ty-jobcard-top { display: flex; justify-content: space-between; align-items: center; gap: 8px; }
.ty-jobcard-title { font: 600 13.5px var(--ty-font-base, inherit); color: var(--ty-color-text, #1c2128); }
.ty-jobcard-meta {
    display: flex;
    align-items: center;
    gap: 7px;
    margin-top: 5px;
    font: 400 12px var(--ty-font-base, inherit);
    color: var(--ty-color-text-muted, #57606a);
}
.ty-jobcard-meta .ty-domain-glyph { color: var(--ty-color-primary, #1b6ec2); font-size: 13px; }
.ty-avatar {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    border-radius: 999px;
    background: var(--ty-color-primary, #1b6ec2);
    color: var(--ty-color-primary-contrast, #fff);
    font-weight: 700;
    flex: none;
    width: 18px;
    height: 18px;
    font-size: 8px;
}

/* ---- Status pills ---------------------------------------------------------- */
.ty-pill {
    display: inline-flex;
    align-items: center;
    gap: 5px;
    font: 600 10.5px var(--ty-font-base, inherit);
    padding: 3px 9px;
    border-radius: var(--ty-radius-pill, 999px);
    white-space: nowrap;
}
.ty-pill.tone-neutral { color: var(--ty-color-text-muted, #57606a); background: var(--ty-color-surface-3, #eef1f4); }
.ty-pill.tone-info    { color: var(--ty-color-info-ink, #1457b0);    background: var(--ty-color-info-soft, #eaf2fd); }
.ty-pill.tone-success { color: var(--ty-color-success-ink, #1a7f37); background: var(--ty-color-success-soft, #e6f6ea); }
.ty-pill.tone-warning { color: var(--ty-color-warning-ink, #9a5b00); background: var(--ty-color-warning-soft, #fdf1dd); }
.ty-pill.tone-danger  { color: var(--ty-color-danger-ink, #b32121);  background: var(--ty-color-danger-soft, #fdecec); }

/* ---- Week view ------------------------------------------------------------- */
.ty-week { display: grid; grid-template-columns: repeat(7, minmax(0, 1fr)); gap: 8px; }
.ty-week-col { display: flex; flex-direction: column; min-width: 0; }
.ty-week-colhead {
    text-align: center;
    padding: 6px 0 9px;
    font: 600 11px var(--ty-font-base, inherit);
    color: var(--ty-color-text-muted, #57606a);
}
.ty-week-colhead .dow { display: block; text-transform: uppercase; letter-spacing: .06em; font-size: 10px; color: var(--ty-color-text-subtle, #8a95a1); }
/* The date is a button into Day view, dressed as the plain number it replaced. */
.ty-week-colhead .dom {
    display: inline-flex; align-items: center; justify-content: center;
    width: 26px; height: 26px; border-radius: 999px; margin-top: 3px;
    appearance: none; border: 0; background: none; padding: 0; cursor: pointer;
    font: inherit; color: inherit;
}
.ty-week-colhead .dom:hover { background: var(--ty-color-surface-3, #eef1f4); color: var(--ty-color-primary, #1b6ec2); }
.ty-week-colhead .dom:focus-visible { outline: 2px solid var(--ty-color-primary, #1b6ec2); outline-offset: 1px; }
.ty-week-colhead.today .dom { background: var(--ty-color-primary, #1b6ec2); color: var(--ty-color-primary-contrast, #fff); }
.ty-week-colhead.today .dom:hover { background: var(--ty-color-primary, #1b6ec2); color: var(--ty-color-primary-contrast, #fff); filter: brightness(1.08); }
/* SELECTED, not today: today is a filled disc, the selection is a ring — so a day can be both and still
   read as both. The column below it takes a matching tint, because in a seven-column week a ring on one
   small number is easy to miss. */
.ty-week-colhead.selected .dom { box-shadow: 0 0 0 2px var(--ty-color-primary, #1b6ec2); color: var(--ty-color-primary, #1b6ec2); }
.ty-week-colhead.today.selected .dom { box-shadow: 0 0 0 2px var(--ty-color-surface, #fff), 0 0 0 4px var(--ty-color-primary, #1b6ec2); color: var(--ty-color-primary-contrast, #fff); }
.ty-week-col.selected .ty-week-cells {
    border-color: var(--ty-color-primary, #1b6ec2);
    background: color-mix(in srgb, var(--ty-color-primary, #1b6ec2) 6%, var(--ty-color-surface-2, #f6f8fa));
}
.ty-week-cells {
    flex: 1;
    display: flex;
    flex-direction: column;
    gap: 6px;
    background: var(--ty-color-surface-2, #f6f8fa);
    border: 1px solid var(--ty-color-border, #e2e6ea);
    border-radius: var(--ty-radius-card, 12px);
    padding: 7px;
    /* Sized so two full-height chips and the drop gap fit without the cell scrolling. */
    min-height: 148px;
}

/* The board's period heading — the same shape as a month grid's own header (period · badge · count), so
   Day, Week, List and Month all announce themselves the same way. Set a size up from the month headers
   because there is only ever one of these, where a three-month spread carries three. */
.ty-period {
    display: flex;
    align-items: baseline;
    gap: 9px;
    margin: 0 2px 12px;
    padding-bottom: 8px;
    border-bottom: 1px solid var(--ty-color-border, #e2e6ea);
}
.ty-period-name {
    margin: 0;
    font: var(--ty-weight-bold, 700) 19px var(--ty-font-base, inherit);
    letter-spacing: -0.015em;
    color: var(--ty-color-text, #1c2128);
}
.ty-period-sub { margin-left: 7px; font-weight: 500; font-size: 17px; color: var(--ty-color-text-subtle, #8a95a1); }

/* ---- Month view ------------------------------------------------------------ */
/* One month or two, laid out by the same rule: months stack in a grid, and "dual" simply gives that grid
   two columns. Below ~1100px two months side by side would squeeze each week to unusable width, so they
   fall back to stacking — still two months, still both live drop zones, just one above the other. */
.ty-months { display: grid; gap: 20px; }
.ty-months--multi { gap: 14px 18px; }
.ty-months--c2 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
.ty-months--c3 { grid-template-columns: repeat(3, minmax(0, 1fr)); }
/* Three across needs real width; below it they drop to two, then to a single column. Still every month
   asked for, still every grid a live drop zone — just stacked, so a cross-month drag survives the reflow. */
@media (max-width: 1500px) { .ty-months--c3 { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
@media (max-width: 1100px) { .ty-months--c2, .ty-months--c3 { grid-template-columns: minmax(0, 1fr); } }

.ty-month { min-width: 0; }
.ty-month-head {
    display: flex;
    align-items: baseline;
    gap: 9px;
    margin: 0 2px 9px;
    padding-bottom: 7px;
    border-bottom: 1px solid var(--ty-color-border, #e2e6ea);
}
.ty-month-name {
    margin: 0;
    font: var(--ty-weight-bold, 700) 17px var(--ty-font-base, inherit);
    letter-spacing: -0.01em;
    color: var(--ty-color-text, #1c2128);
}
.ty-month-year { margin-left: 7px; font-weight: 500; color: var(--ty-color-text-subtle, #8a95a1); }
.ty-month-badge {
    font: 600 10px var(--ty-font-base, inherit);
    letter-spacing: .06em;
    text-transform: uppercase;
    padding: 2px 7px;
    border-radius: 999px;
    background: var(--ty-color-primary, #1b6ec2);
    color: var(--ty-color-primary-contrast, #fff);
}
.ty-month-count { margin-left: auto; font: 500 11.5px var(--ty-font-base, inherit); color: var(--ty-color-text-subtle, #8a95a1); }

.ty-month-dowrow { display: grid; grid-template-columns: repeat(7, 1fr); margin-bottom: 6px; }
.ty-month-dow { text-align: center; font: 600 10px var(--ty-font-base, inherit); letter-spacing: .06em; text-transform: uppercase; color: var(--ty-color-text-subtle, #8a95a1); }
.ty-month-grid {
    display: grid;
    grid-template-columns: repeat(7, 1fr);
    gap: 6px;
}
.ty-month-cell {
    /* Was 92px, which fitted three of the old thin chips. With the bigger grab target it holds two plus the
       date, which is the realistic case for a day in a month view — a busier day scrolls within the cell. */
    min-height: 124px;
    background: var(--ty-color-surface, #fff);
    border: 1px solid var(--ty-color-border, #e2e6ea);
    border-radius: 10px;
    padding: 6px;
    display: flex;
    flex-direction: column;
    gap: 5px;
    /* Vertical scroll rather than clip: with the taller chips a busy day can exceed the cell, and a job you
       cannot see is a job that does not get done. Horizontal stays hidden so the grid never smears sideways. */
    overflow: hidden auto;
}
.ty-month-cell.other-month { background: var(--ty-color-surface-2, #f6f8fa); opacity: .7; }
/* The date doubles as the doorway into Day view, so it is a real button — stripped back to look exactly
   like the plain number it replaced until you point at it, and given a 22px minimum so it is hittable. */
.ty-month-date {
    appearance: none; background: none; border: 0; padding: 0; cursor: pointer;
    font: 600 11.5px var(--ty-font-base, inherit); color: var(--ty-color-text-muted, #57606a);
    align-self: flex-start; min-width: 22px; height: 22px; border-radius: 999px; text-align: center;
    display: inline-flex; align-items: center; justify-content: center;
}
.ty-month-date:hover { background: var(--ty-color-surface-3, #eef1f4); color: var(--ty-color-primary, #1b6ec2); }
.ty-month-date:focus-visible { outline: 2px solid var(--ty-color-primary, #1b6ec2); outline-offset: 1px; }
.ty-month-cell.today .ty-month-date {
    display: inline-flex; align-items: center; justify-content: center;
    width: 22px; height: 22px; border-radius: 999px;
    background: var(--ty-color-primary, #1b6ec2); color: var(--ty-color-primary-contrast, #fff);
}
.ty-month-more {
    appearance: none; border: 0; cursor: pointer;
    display: inline-flex; align-items: center; gap: 3px;
    align-self: flex-start; padding: 2px 6px; border-radius: 999px;
    background: var(--ty-color-surface-3, #eef1f4);
    font: 600 10px var(--ty-font-base, inherit); color: var(--ty-color-text-muted, #57606a);
}
.ty-month-more:hover { background: color-mix(in srgb, var(--ty-color-primary, #1b6ec2) 12%, transparent); color: var(--ty-color-primary, #1b6ec2); }
.ty-month-more:focus-visible { outline: 2px solid var(--ty-color-primary, #1b6ec2); outline-offset: 1px; }
.ty-month-more .ty-glyph { width: 10px; height: 10px; }

/* Expanded: the cell stops holding its contents back and grows to list every job for that day, so nothing
   is hidden behind a count. The week's row grows with it — the honest cost of seeing a busy day in full.
   It lifts off the grid rather than taking a ring, because the ring means something else here: selection. */
.ty-month-cell.is-expanded {
    overflow: visible;
    border-color: var(--ty-color-primary, #1b6ec2);
    box-shadow: 0 8px 20px rgba(0,0,0,.10);
}
/* SELECTED — the one day the whole page agrees on. It survives every view switch, so the month grid has to
   show it plainly: an accent ring and a tint, distinct from today's filled date disc (a day is often both)
   and from the expanded cell's lift. */
.ty-month-cell.is-selected {
    border-color: var(--ty-color-primary, #1b6ec2);
    box-shadow: 0 0 0 2px var(--ty-color-primary, #1b6ec2);
    background: color-mix(in srgb, var(--ty-color-primary, #1b6ec2) 7%, var(--ty-color-surface, #fff));
}
.ty-month-cell.is-selected.other-month { opacity: 1; }
.ty-month-cell.is-selected.is-expanded { box-shadow: 0 0 0 2px var(--ty-color-primary, #1b6ec2), 0 8px 20px rgba(0,0,0,.10); }
/* Not today, but selected: give the date the same ring so the cell and its number agree. */
.ty-month-cell.is-selected:not(.today) .ty-month-date { color: var(--ty-color-primary, #1b6ec2); }
/* A spill-over day that belongs to the OTHER grid on screen: it holds the week's shape and nothing else —
   no date, no chips, and deliberately not a drop zone, so each date exists exactly once on the page. */
.ty-month-pad { background: transparent; border-color: transparent; min-height: 0; }
/* Two months share the width one had, so the cells give back what they can: less height, smaller dates. */
.ty-months--multi .ty-month-grid { gap: 5px; }
.ty-months--multi .ty-month-cell { min-height: 108px; padding: 5px; gap: 4px; }
.ty-months--multi .ty-month-date { font-size: 11px; }
.ty-months--multi .ty-month-cell.today .ty-month-date { width: 20px; height: 20px; }
.ty-months--multi .ty-month-weather { font-size: .95rem; margin-top: -18px; }
/* A half-width cell cannot hold time and name on one line — laid out side by side the name is squeezed to
   nothing and the chip reads "08", which identifies no job at all. So the chip WRAPS: time on top, name
   beneath, both legible. The trade still reads from the coloured edge, so the domain glyph stands down. */
.ty-months--multi .ty-jobchip { min-height: 34px; font-size: 11px; gap: 0; }
.ty-months--multi .ty-drag-grip--chip { width: 13px; background-size: 5px 5px; }
.ty-months--multi .ty-jobchip-open { padding: 4px 6px; gap: 4px; flex-wrap: wrap; align-items: baseline; align-content: center; }
/* The trade icon stays on every chip in every month layout — smaller when two or three months share the width. */
.ty-months--multi .ty-jobchip .ty-domain-glyph { font-size: 11px; margin-right: 3px; }
.ty-months--multi .ty-jobchip .ty-jobchip-title { flex: 1 0 100%; font-weight: 600; }
/* A third of the width again — a day cell is now ~55px, and the first casualty is the one thing that must
   never be cut: the TIME. Left to shrink it renders "08:0", which is not a time. So at three across the
   time is pinned to its natural width and the customer name takes whatever is left (with the full name in
   the chip's tooltip, and the whole day one click away). Everything else — padding, grip, type — gives way.
   Only while three really ARE across: below 1500px they fall back to two columns and the c2 sizing. */
@media (min-width: 1501px) {
    .ty-months--c3 .ty-month-grid { gap: 4px; }
    .ty-months--c3 .ty-month-cell { min-height: 96px; padding: 4px; gap: 3px; }
    .ty-months--c3 .ty-month-dow { font-size: 9px; letter-spacing: .02em; }
    .ty-months--c3 .ty-month-name { font-size: 15px; }
    .ty-months--c3 .ty-month-head { gap: 6px; margin-bottom: 7px; }
    .ty-months--c3 .ty-jobchip { min-height: 30px; font-size: 10px; }
    .ty-months--c3 .ty-drag-grip--chip { width: 8px; background-size: 4px 4px; }
    .ty-months--c3 .ty-jobchip-open { padding: 3px 4px; gap: 2px; }
    .ty-months--c3 .ty-jobchip-time { flex: 0 0 auto; white-space: nowrap; font-size: 10px; }
    .ty-months--c3 .ty-jobchip-title { font-size: 10px; }
    /* "+1 more" has to fit inside a ~48px cell or it is clipped to "+1 mor", which looks broken. The
       chevron is the first thing to go: the pill is plainly a control from its shape and its hover. */
    .ty-months--c3 .ty-month-more { font-size: 9px; padding: 1px 4px; gap: 0; }
    .ty-months--c3 .ty-month-more .ty-glyph { display: none; }
}
/* The pill says "+2 more", never "+2" over "more". */
.ty-month-more { white-space: nowrap; }
/* One expanded cell should not drag six empty neighbours up to its height. Stretch is right for a normal
   row (equal cells); the moment a row contains an expanded cell, the others keep their own height. */
.ty-month-grid:has(.is-expanded) { align-items: start; }

/* ---- Job chip (week + month) ----------------------------------------------- */
.ty-jobchip {
    appearance: none;
    display: flex;
    /* stretch, not center: both halves must fill the chip's height, or the click target ends up shorter
       than the chip looks and the grip stands proud of it. The inner button centres its own content. */
    align-items: stretch;
    gap: 6px;
    text-align: left;
    width: 100%;
    border: 0;
    border-left: 4px solid var(--ty-color-primary, #1b6ec2);
    background: var(--ty-color-primary-soft, #eef4fd);
    color: var(--ty-color-text, #1c2128);
    border-radius: 8px;
    padding: 0;
    font: 600 12.5px var(--ty-font-base, inherit);
    min-width: 0;
    overflow: hidden;
    /* A drag handle you can hit without aiming. 36px is comfortable with a mouse; the coarse-pointer rule
       below takes it to the 44px thumb target, because the week and month views are where a round gets
       shuffled on a phone in a van. */
    min-height: 36px;
}

/* The chip's clickable half. Carries the padding the chip used to have, so the text sits where it did. */
.ty-jobchip-open {
    appearance: none;
    flex: 1;
    min-width: 0;
    display: flex;
    align-items: center;
    gap: 6px;
    text-align: left;
    background: none;
    border: 0;
    padding: 8px 10px;
    font: inherit;
    color: inherit;
    cursor: pointer;
}

/* ---- The grab handle (day, week and month) ---------------------------------
   The visible answer to "where do I take hold of this?". A tinted strip down the leading edge, carrying
   the standard six-dot grip, on every draggable item in all three views. It is deliberately the ONLY place
   a drag starts — the rest of the card opens the job — so a press either moves the item or opens it, and
   never has to guess which was meant. */
.ty-drag-grip {
    flex: none;
    align-self: stretch;
    width: 26px;
    cursor: grab;
    background-color: color-mix(in srgb, var(--ty-color-primary, #1b6ec2) 12%, transparent);
    border-right: 1px solid color-mix(in srgb, var(--ty-color-primary, #1b6ec2) 18%, transparent);
    /* Two columns of three dots, drawn rather than iconed so it scales with the strip and needs no font. */
    background-image: radial-gradient(currentColor 1.4px, transparent 1.5px);
    background-size: 7px 7px;
    background-position: center;
    background-repeat: repeat-y;
    color: color-mix(in srgb, var(--ty-color-primary, #1b6ec2) 55%, transparent);
    transition: background-color var(--ty-motion-micro, 120ms) ease, color var(--ty-motion-micro, 120ms) ease;
}

.ty-drag-grip:hover {
    background-color: color-mix(in srgb, var(--ty-color-primary, #1b6ec2) 22%, transparent);
    color: var(--ty-color-primary, #1b6ec2);
}

.ty-drag-grip:active { cursor: grabbing; }

/* Chips are short, so the grip narrows — still a full-height strip, still unmistakable. */
.ty-drag-grip--chip {
    width: 20px;
    background-size: 6px 6px;
}

@media (pointer: coarse) {
    .ty-drag-grip { width: 34px; }
    .ty-drag-grip--chip { width: 28px; }
}

@media (pointer: coarse) {
    .ty-jobchip { min-height: 44px; padding: 10px 12px; font-size: 13px; }
}
.ty-jobchip .ty-domain-glyph { color: var(--ty-color-primary, #1b6ec2); font-size: 13px; }
.ty-jobchip .ty-jobchip-time { color: var(--ty-color-text-muted, #57606a); font-weight: 700; }
.ty-jobchip .ty-jobchip-title { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

/* An arrangement re-timed this job: the shown time leads, the booked original sits beside it struck
   through — "worked at 08:30, was booked 13:00" at a glance, on chips and day cards alike. */
.ty-time-was {
    font: 600 10px var(--ty-font-base, inherit);
    color: var(--ty-color-text-subtle, #8a95a1);
    text-decoration: line-through;
    white-space: nowrap;
}
.ty-time-shift { white-space: nowrap; font-weight: 600; }

/* ---- Side panel (detail) --------------------------------------------------- */
.ty-panel-overlay {
    position: fixed;
    inset: 0;
    background: rgba(var(--ty-color-overlay-rgb, 12, 18, 28), .38);
    display: flex;
    justify-content: flex-end;
    z-index: var(--ty-z-modal, 400);
    animation: ty-fade var(--ty-motion-standard, 200ms) ease;
}
.ty-panel {
    /* Matches the customer panel (TyDetailPanel `.dp`): a job carries a real record — the domain detail
       component, its notes, its history — and 420px was squeezing that into a column. Same width, same
       breakpoint, so the two panels feel like one thing in two places rather than two conventions. */
    width: min(64rem, 100vw);
    max-width: 100%;
    height: 100%;
    background: var(--ty-color-surface, #fff);
    box-shadow: var(--ty-shadow-lg, -8px 0 30px -12px rgba(0,0,0,.4));
    display: flex;
    flex-direction: column;
    overflow-y: auto;
    animation: ty-slidein var(--ty-motion-standard, 200ms) var(--ty-ease, ease);
}
@keyframes ty-fade { from { opacity: 0; } to { opacity: 1; } }
@keyframes ty-slidein { from { transform: translateX(24px); } to { transform: translateX(0); } }

.ty-panel-head { padding: 16px 18px 0; color: var(--ty-color-primary-contrast, #fff); background: linear-gradient(160deg, var(--ty-color-primary, #1b6ec2), var(--ty-color-primary-ink, #155a9c)); }
.ty-panel-headrow { display: flex; justify-content: space-between; align-items: flex-start; gap: 10px; }
.ty-panel-idwrap { display: flex; gap: 11px; align-items: center; min-width: 0; }
/* Same reasoning as the customer panel: below this, the sliver of board left beside a 64rem panel is too
   narrow to be useful, so take the screen instead. */
@media (max-width: 80rem) {
    .ty-panel { width: 100vw; }
}

.ty-panel-avatar { width: 38px; height: 38px; border-radius: 10px; background: rgba(255,255,255,.16); display: flex; align-items: center; justify-content: center; font-size: 18px; flex: none; }
.ty-panel-title { font: 700 16px var(--ty-font-base, inherit); letter-spacing: -.01em; }
.ty-panel-sub { font: 500 11.5px var(--ty-font-base, inherit); opacity: .85; margin-top: 2px; }
.ty-panel-ref { font-family: var(--ty-font-mono, ui-monospace, Menlo, monospace); }
.ty-panel-close { appearance: none; border: 0; background: rgba(255,255,255,.16); color: var(--ty-color-primary-contrast, #fff); width: 28px; height: 28px; border-radius: 8px; cursor: pointer; display: inline-flex; align-items: center; justify-content: center; flex: none; }
.ty-panel-close-float { position: absolute; top: 15px; right: 16px; z-index: 1; }

/* "Directions" floated into the panel's coloured header, beside the close button. The header is a strong
   colour, so the link keeps its white pill background for contrast rather than inheriting it. */
.ty-panel-dir { position: absolute; top: 14px; right: 54px; z-index: 1; }
.ty-panel-pills { display: flex; gap: 8px; flex-wrap: wrap; margin: 14px 0 15px; }
.ty-panel-pills .ty-pill.on-primary { background: var(--ty-color-surface, #fff); color: var(--ty-color-primary-ink, #1457b0); }
.ty-panel-pills .ty-pill.on-glass { background: rgba(255,255,255,.18); color: var(--ty-color-primary-contrast, #fff); }
.ty-panel-tabs { display: flex; gap: 2px; overflow-x: auto; }
.ty-panel-tab {
    font: 600 11.5px var(--ty-font-base, inherit);
    padding: 11px 10px;
    white-space: nowrap;
    color: rgba(255,255,255,.72);
    border-bottom: 2.5px solid transparent;
    background: none; border-top: 0; border-left: 0; border-right: 0;
    cursor: pointer;
    display: inline-flex; align-items: center; gap: 6px;
}
.ty-panel-tab.on { color: var(--ty-color-primary-contrast, #fff); border-bottom-color: var(--ty-color-primary-contrast, #fff); }

.ty-panel-body { padding: 18px 20px 22px; }
.ty-sect { margin-bottom: 17px; }
.ty-sect:last-child { margin-bottom: 0; }
.ty-sect-label {
    font: 700 10px var(--ty-font-base, inherit);
    letter-spacing: .11em;
    text-transform: uppercase;
    color: var(--ty-color-text-subtle, #aab3bd);
    margin: 0 0 9px;
    display: flex;
    align-items: center;
    gap: 7px;
}
.ty-sect-label .ty-domain-glyph, .ty-sect-label .ty-glyph { color: var(--ty-color-primary, #1b6ec2); font-size: 11px; }
.ty-kv { display: flex; justify-content: space-between; gap: 12px; padding: 5px 0; font: 400 12.5px var(--ty-font-base, inherit); color: var(--ty-color-text-muted, #57606a); }
.ty-kv b { font-weight: 600; color: var(--ty-color-text, #1c2128); text-align: right; }
.ty-kv b.ok { color: var(--ty-color-success-ink, #1a7f37); }
.ty-kv b.warn { color: var(--ty-color-warning-ink, #9a5b00); }
.ty-divider { height: 1px; background: var(--ty-color-border, #eef1f4); margin: 15px 0; }
.ty-tags { display: flex; gap: 8px; flex-wrap: wrap; }
.ty-tag { display: inline-flex; align-items: center; gap: 5px; font: 600 10.5px var(--ty-font-base, inherit); padding: 4px 10px; border-radius: var(--ty-radius-pill, 999px); color: var(--ty-color-primary-ink, #1457b0); background: var(--ty-color-primary-soft, #eef4fd); }
.ty-check-row { display: flex; align-items: center; gap: 9px; padding: 4px 0; font: 400 12.5px var(--ty-font-base, inherit); color: var(--ty-color-text-muted, #57606a); }
.ty-check-box { width: 17px; height: 17px; border-radius: 5px; border: 1.5px solid var(--ty-color-border-strong, #cdd5de); flex: none; display: inline-flex; align-items: center; justify-content: center; }
.ty-check-box.done { background: var(--ty-color-primary, #1b6ec2); border-color: var(--ty-color-primary, #1b6ec2); color: var(--ty-color-primary-contrast, #fff); font-size: 10px; }
.ty-note { display: flex; gap: 8px; align-items: flex-start; padding: 9px 11px; border-radius: 9px; background: var(--ty-color-warning-soft, #fbf0db); color: var(--ty-color-warning-ink, #7a5209); font: 500 11px/1.4 var(--ty-font-base, inherit); margin-top: 9px; }

/* ---- Responsive ------------------------------------------------------------ */
@media (max-width: 720px) {
    .ty-week { grid-template-columns: 1fr; }
    .ty-panel { width: 100%; }
}

@media (prefers-reduced-motion: reduce) {
    .ty-panel, .ty-panel-overlay { animation: none; }
    .ty-jobcard { transition: none; }
}

/* ---- "Open in Schedule/Planner" focus pulse (jobFocus.js) ------------------- */
/* Shared by the schedule board and both planning pages (all three load this stylesheet) — landing on a
   specific job from JobContextBar briefly rings the card so it's obvious which one, on top of the scroll
   that already brought it into view. */
@keyframes ty-focus-pulse-ring {
    0%   { box-shadow: 0 0 0 0 color-mix(in srgb, var(--ty-color-primary, #1b6ec2) 55%, transparent); }
    70%  { box-shadow: 0 0 0 12px color-mix(in srgb, var(--ty-color-primary, #1b6ec2) 0%, transparent); }
    100% { box-shadow: 0 0 0 0 transparent; }
}
.ty-focus-pulse { animation: ty-focus-pulse-ring 1.1s ease-out 2; border-radius: inherit; }
@media (prefers-reduced-motion: reduce) {
    /* No ring animation, but the card still needs to read as "this one" for a moment. */
    .ty-focus-pulse { animation: none; outline: 3px solid var(--ty-color-primary, #1b6ec2); outline-offset: 2px; }
}

/* ---- Weather --------------------------------------------------------------- */
/* Per-day forecast so a tradesman can plan around the weather. Icons are big + colour-coded by condition. */
.ty-week-weather {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 1px;
    margin-top: 5px;
}
.ty-week-weather .ty-wx { font-size: 1.65rem; line-height: 1; }
.ty-week-weather-temp { font: 700 12px var(--ty-font-base, inherit); color: var(--ty-color-text, #1c2128); }
.ty-week-weather-min { color: var(--ty-color-text-subtle, #8a95a1); font-weight: 600; margin-left: 3px; }
.ty-week-weather-precip {
    display: inline-flex;
    align-items: center;
    gap: 2px;
    font: 600 10px var(--ty-font-base, inherit);
    color: var(--ty-color-info, #4a90d9);
}
.ty-week-weather-precip i { font-size: 9px; }

/* Day view: a weather banner above the agenda. */
.ty-day-weather {
    display: flex;
    align-items: center;
    gap: 10px;
    flex-wrap: wrap;
    padding: 10px 14px;
    margin-bottom: 10px;
    background: var(--ty-color-surface-2, #f6f8fa);
    border: 1px solid var(--ty-color-border, #e2e6ea);
    border-radius: var(--ty-radius-card, 12px);
}
.ty-day-weather .ty-wx { font-size: 2.4rem; line-height: 1; }
.ty-day-weather-cond { font: 600 15px var(--ty-font-base, inherit); color: var(--ty-color-text, #1c2128); }
.ty-day-weather-temp { font: 700 15px var(--ty-font-base, inherit); color: var(--ty-color-text, #1c2128); }
.ty-day-weather-precip {
    display: inline-flex; align-items: center; gap: 3px;
    font: 600 13px var(--ty-font-base, inherit); color: var(--ty-color-info, #4a90d9);
}

/* Month view: a small condition icon by the date. */
.ty-month-weather { font-size: 1.05rem; line-height: 1; align-self: flex-end; margin-top: -20px; }

/* Condition-coloured weather icons (keyed to WmoWeatherCodes.Kind); values read on Trusty + Graft. */
.ty-wx { flex: none; }
/* Weather glyph tints are METEOROLOGICAL ICONOGRAPHY, not app colour: sunny is yellow and
   rain is blue on every theme, the same way a domain glyph is not re-hued. Verified >= 3:1
   (the non-text contrast floor) against both Trusty's #ffffff card and Graft's #16202b. */
.ty-wx--clear { color: #f4b400; }        /* sunny → yellow */
.ty-wx--night { color: #9aa7c7; }        /* clear night → pale indigo */
.ty-wx--partlycloudy { color: #7f9bc4; } /* sun + cloud → soft blue-grey */
.ty-wx--cloudy { color: #8a94a0; }       /* overcast → grey */
.ty-wx--fog { color: #a6aeb8; }          /* fog/mist → light grey */
.ty-wx--rain { color: #4a90d9; }         /* drizzle / rain / showers → blue */
.ty-wx--snow { color: #5fc6e0; }         /* snow → icy cyan */
.ty-wx--thunder { color: #7a5ad8; }      /* thunderstorm → purple */


/* ── Drag and drop ────────────────────────────────────────────────────────────────────────────────
   The gesture is driven client-side (wwwroot/scheduleDnd.js): while a card is in the air the JS puts
   .ty-dnd-active on the board, .ty-dnd-source on the card in hand, .ty-drop-over on the zone under the
   pointer, and — where the landing order can really be kept — opens a gap between the neighbouring
   cards (.ty-dnd-gap-above / -below) and parks the dashed .ty-dnd-marker preview slot in it. Day view
   is an hour ladder so a drop also sets the time. */
.ty-draggable { cursor: grab; }
.ty-draggable:active { cursor: grabbing; }
.ty-dnd-source { opacity: .4; transform: scale(.98); }

.ty-agenda-row--slot { min-height: 2.2rem; border-radius: 10px; transition: background .15s, min-height .2s, outline-color .15s; outline: 2px dashed transparent; outline-offset: -2px; }
.ty-agenda-row--empty .ty-agenda-time { opacity: .45; }
.ty-agenda-slot { flex: 1; display: flex; flex-direction: column; gap: 8px; min-width: 0; }
.ty-dnd-active .ty-agenda-row--slot { min-height: 3rem; outline-color: var(--ty-color-border, #e5e7eb); }
.ty-dnd-active .ty-agenda-row--empty { background: var(--ty-color-surface-sunken, #f6f8fb); }
.ty-dnd-active .ty-agenda-empty { display: none; }

.ty-week-cells, .ty-month-cell { transition: background .15s, box-shadow .15s; }
.ty-drop-over {
    background: color-mix(in srgb, var(--ty-color-primary, #1b6ec2) 10%, var(--ty-color-surface, #fff)) !important;
    box-shadow: inset 0 0 0 2px var(--ty-color-primary, #1b6ec2);
    outline-color: var(--ty-color-primary, #1b6ec2) !important;
}

/* The insertion preview: a real gap opens (the size of the card in hand — set by the JS as
   --ty-dnd-size) and the dashed slot sits in it saying "it will land HERE". Margins rather than
   transforms so the layout truly makes room instead of cards painting over one another. */
[data-dnd-item] { transition: margin .14s ease; }
.ty-dnd-gap-above { margin-top: calc(var(--ty-dnd-size, 44px) + 10px) !important; }
.ty-dnd-gap-below { margin-bottom: calc(var(--ty-dnd-size, 44px) + 10px) !important; }

.ty-dnd-marker {
    position: fixed;
    z-index: var(--ty-z-modal, 400);
    pointer-events: none;
    display: none;
    border: 2px dashed var(--ty-color-primary, #1b6ec2);
    border-radius: 10px;
    background: color-mix(in srgb, var(--ty-color-primary, #1b6ec2) 8%, transparent);
    transition: top .12s ease, left .12s ease, width .12s ease;
}
.ty-dnd-marker.on { display: block; }

/* Spring-loaded paging: while a card is in the air the prev/next arrows light up as somewhere a drag
   can be TAKEN (ready), and holding the card over one arms it — the calendar pages after a short dwell
   and keeps paging while held, so any month is reachable without letting go. */
[data-dnd-nav].ty-dnd-nav-ready {
    color: var(--ty-color-primary, #1b6ec2);
    background: color-mix(in srgb, var(--ty-color-primary, #1b6ec2) 8%, transparent);
}
[data-dnd-nav].ty-dnd-nav-armed {
    color: var(--ty-color-primary-contrast, #fff);
    background: var(--ty-color-primary, #1b6ec2);
    animation: ty-dnd-nav-pulse .65s ease-in-out infinite;
}
@keyframes ty-dnd-nav-pulse {
    0%, 100% { box-shadow: 0 0 0 0 color-mix(in srgb, var(--ty-color-primary, #1b6ec2) 45%, transparent); }
    50% { box-shadow: 0 0 0 5px color-mix(in srgb, var(--ty-color-primary, #1b6ec2) 20%, transparent); }
}
@media (prefers-reduced-motion: reduce) {
    [data-dnd-nav].ty-dnd-nav-armed { animation: none; }
}

@media (prefers-reduced-motion: reduce) {
    [data-dnd-item], .ty-dnd-marker, .ty-agenda-row--slot { transition: none; }
}

/* ── Within-day ordering ──────────────────────────────────────────────────────────────────────────
   A trade that keeps a manual working order (a round's stop order) gets two things on the board: a card
   can be dropped ONTO another card of the same trade to take its place, and — because a drag is a poor
   gesture on a phone in a van — a pair of nudge buttons beside the card. Both go through the same seam. */
.ty-agenda-item { display: flex; align-items: stretch; gap: 6px; min-width: 0; }
.ty-agenda-item > .ty-jobcard { flex: 1; min-width: 0; }

.ty-order-ctl { display: flex; flex-direction: column; justify-content: center; gap: 4px; flex: 0 0 auto; }
.ty-order-btn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    /* 32px is the smallest a gloved thumb reliably hits; the pair still stacks inside a card's height. */
    width: 32px;
    min-height: 32px;
    padding: 0;
    border: 1px solid var(--ty-color-border, #e5e7eb);
    border-radius: 8px;
    background: var(--ty-color-surface, #fff);
    color: var(--ty-color-text-muted, #6b7280);
    cursor: pointer;
    transition: background .15s, color .15s, border-color .15s;
}
.ty-order-btn:hover:not(:disabled) {
    background: var(--ty-color-surface-sunken, #f6f8fb);
    border-color: var(--ty-color-primary, #1b6ec2);
    color: var(--ty-color-primary, #1b6ec2);
}
.ty-order-btn:focus-visible { outline: 2px solid var(--ty-color-primary, #1b6ec2); outline-offset: 2px; }
.ty-order-btn:disabled { opacity: .35; cursor: default; }

/* The card's one-tap skip / put-back, sharing the nudge buttons' column. Skip warms to the danger tone
   on hover (it sets the visit aside); put-back to the success tone (it returns it to the plan). */
.ty-skip-btn:hover:not(:disabled) {
    background: var(--ty-color-danger-soft, #fdecec);
    border-color: var(--ty-color-danger-ink, #b32121);
    color: var(--ty-color-danger-ink, #b32121);
}
.ty-replan-btn:hover:not(:disabled) {
    background: var(--ty-color-success-soft, #e6f6ea);
    border-color: var(--ty-color-success-ink, #1a7f37);
    color: var(--ty-color-success-ink, #1a7f37);
}


/* ============================================================================
   Big, bold, a little playful — the schedule's size-and-spirit pass (2026-09-03),
   the same treatment Planning V2 got. Appended last so it wins over the base
   rules above; everything stays token-driven. Tweak here, not in the base.
   ============================================================================ */
.ty-sched { }

/* Header: the page says its name, the controls are thumb-sized. */
.ty-sched-head { gap: 14px; margin-bottom: 18px; }
.ty-sched-title { font-size: 28px; letter-spacing: -0.02em; font-weight: 800; }
.ty-datenav { padding: 5px 8px; border-radius: 14px; gap: 6px; border-width: 2px; }
.ty-datenav-label { font: 800 17px var(--ty-font-base, inherit); min-width: 11ch; }
.ty-iconbtn { width: 36px; height: 36px; border-radius: 10px; font-size: 16px; transition: background .15s, transform .18s cubic-bezier(.34, 1.56, .64, 1); }
.ty-iconbtn:hover { transform: scale(1.08); }
.ty-today-btn { font: 800 14px var(--ty-font-base, inherit); padding: 10px 16px; border-radius: 12px; border-width: 2px; transition: transform .18s cubic-bezier(.34, 1.56, .64, 1), border-color .15s, color .15s; }
.ty-today-btn:hover { transform: translateY(-1px) scale(1.03); border-color: var(--ty-color-primary, #1b6ec2); color: var(--ty-color-primary, #1b6ec2); }
.ty-btn-primary { font-size: 14.5px; font-weight: 800; padding: 10px 18px; border-radius: 14px; transition: transform .18s cubic-bezier(.34, 1.56, .64, 1), filter .15s, box-shadow .15s; box-shadow: var(--ty-shadow-md, 0 6px 16px -10px rgba(0,0,0,.45)); }
.ty-btn-primary:hover { transform: translateY(-1px) scale(1.03); filter: brightness(1.06); }
.ty-chip { font-size: 13px; font-weight: 800; padding: 7px 13px; border-radius: 999px; transition: transform .18s cubic-bezier(.34, 1.56, .64, 1), background .15s, border-color .15s, color .15s; }
.ty-chip:hover { transform: translateY(-1px) scale(1.04); }
.ty-chip--trade { padding: 7px 11px; }
.ty-chip-ico { font-size: 16px; }
.ty-tour-replay-btn { font-size: 13px; font-weight: 700; }
.ty-monthspan-label { font-size: 12px; font-weight: 800; }

/* The period line: the day in words, big; TODAY as a badge you can see from the van. */
.ty-period { gap: 12px; margin-bottom: 12px; }
.ty-period-name { font-size: 26px; font-weight: 800; letter-spacing: -0.02em; }
.ty-period-sub { font-size: 20px; }
.ty-period .ty-tag, .ty-period .ty-month-badge { font-size: 11.5px; font-weight: 800; padding: 4px 10px; border-radius: 999px; }
.ty-day-weather { padding: 14px 18px; gap: 14px; border-radius: 16px; margin-bottom: 14px; }
.ty-day-weather .ty-wx { font-size: 2.8rem; }
.ty-day-weather-cond, .ty-day-weather-temp { font-size: 17px; font-weight: 800; }
.ty-day-weather-precip { font-size: 14px; font-weight: 700; }

/* Day view: hour labels you can read, cards you can grab. */
.ty-agenda { gap: 14px; }
.ty-agenda-time { width: 58px; font: 800 15px var(--ty-font-base, inherit); color: var(--ty-color-text, #1c2128); padding-top: 14px; }
.ty-agenda-row { gap: 14px; }
.ty-jobcard { border-radius: 16px; border-left-width: 6px; transition: box-shadow .15s, transform .18s cubic-bezier(.34, 1.56, .64, 1); }
.ty-jobcard:hover { transform: translateY(-2px); box-shadow: var(--ty-shadow-md, 0 8px 20px -12px rgba(0,0,0,.4)); }
.ty-jobcard-body { padding: 14px 16px; }
.ty-jobcard-title { font-size: 16.5px; font-weight: 800; }
.ty-jobcard-meta { font-size: 13px; font-weight: 600; margin-top: 4px; gap: 8px; }
.ty-jobcard-meta .ty-domain-glyph { font-size: 15px; }
.ty-avatar { width: 28px; height: 28px; font-size: 11px; font-weight: 800; }
.ty-pill { font-size: 12px; font-weight: 800; padding: 4px 10px; border-radius: 999px; }
.ty-order-btn, .ty-skip-btn, .ty-replan-btn { width: 32px; height: 32px; border-radius: 10px; font-size: 14px; transition: transform .18s cubic-bezier(.34, 1.56, .64, 1), background .15s, color .15s; }
.ty-order-btn:hover, .ty-skip-btn:hover, .ty-replan-btn:hover { transform: scale(1.1); }
.ty-drag-grip { width: 22px; font-size: 14px; }
.ty-agenda-empty { padding: 36px 16px; border-radius: 16px; font-size: 15px; font-weight: 600; }

/* Week view: the day number is the biggest thing in the column. */
.ty-week { gap: 10px; }
.ty-week-colhead { padding: 6px 0 10px; }
.ty-week-colhead .dow { font-size: 11.5px; font-weight: 800; letter-spacing: .08em; }
.ty-week-colhead .dom { font-size: 22px; font-weight: 800; width: 44px; height: 44px; border-radius: 14px; transition: transform .18s cubic-bezier(.34, 1.56, .64, 1), background .15s, color .15s; }
.ty-week-colhead .dom:hover { transform: scale(1.08); }
.ty-week-colhead.today .dom { box-shadow: 0 0 0 4px var(--ty-color-primary-soft, #eef4fd); }
.ty-week-weather .ty-wx { font-size: 1.9rem; }
.ty-week-weather-temp { font-size: 13px; font-weight: 800; }
.ty-week-cells { border-radius: 14px; }
.ty-jobchip { border-radius: 12px; transition: transform .18s cubic-bezier(.34, 1.56, .64, 1), box-shadow .15s; }
.ty-jobchip:hover { transform: translateY(-1px); box-shadow: var(--ty-shadow-sm, 0 2px 8px rgba(0,0,0,.08)); }
.ty-jobchip-open { font-size: 13px; font-weight: 700; padding: 9px 10px; }

/* Week and month chip titles wrap onto their own line(s) instead of shrinking to an initial. */
.ty-week .ty-jobchip-open, .ty-month-cell .ty-jobchip-open { flex-wrap: wrap; row-gap: 2px; }
.ty-week .ty-jobchip .ty-jobchip-title, .ty-month-cell .ty-jobchip .ty-jobchip-title { flex: 1 0 100%; white-space: normal; display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; line-height: 1.2; font-weight: 800; }
.ty-week .ty-jobchip .ty-jobchip-time, .ty-month-cell .ty-jobchip .ty-jobchip-time { font-size: 12px; }

/* Month view: dates as bold numbers, cells with room, today ringed. */
.ty-month-name { font-size: 22px; font-weight: 800; letter-spacing: -0.02em; }
.ty-month-year { font-size: 16px; }
.ty-month-count { font-size: 12.5px; font-weight: 700; }
.ty-month-dow { font-size: 11px; font-weight: 800; padding: 4px 0; }
.ty-month-grid { gap: 8px; }
.ty-month-cell { border-radius: 14px; padding: 8px; min-height: 132px; transition: background .15s, box-shadow .15s, transform .18s cubic-bezier(.34, 1.56, .64, 1); }
.ty-month-cell:hover { box-shadow: var(--ty-shadow-sm, 0 2px 8px rgba(0,0,0,.08)); }
.ty-month-date { font-size: 15px; font-weight: 800; min-width: 30px; height: 30px; color: var(--ty-color-text, #1c2128); transition: transform .18s cubic-bezier(.34, 1.56, .64, 1), background .15s, color .15s; }
.ty-month-date:hover { transform: scale(1.1); }
.ty-month-cell.today { box-shadow: 0 0 0 3px var(--ty-color-primary-soft, #eef4fd); border-color: var(--ty-color-primary, #1b6ec2); }
.ty-month-cell.today .ty-month-date { background: var(--ty-color-primary, #1b6ec2); color: var(--ty-color-primary-contrast, #fff); }
.ty-month-more { font-size: 12px; font-weight: 800; }

@media (prefers-reduced-motion: reduce) {
    .ty-sched *, .ty-sched *::before, .ty-sched *::after { transition: none !important; animation: none !important; }
}
@media (max-width: 600px) {
    .ty-sched-title { font-size: 22px; }
    .ty-period-name { font-size: 21px; }
    .ty-datenav-label { font-size: 15px; min-width: 9ch; }
    .ty-jobcard-title { font-size: 15px; }
    .ty-week-colhead .dom { font-size: 17px; width: 36px; height: 36px; }
    .ty-month-cell { min-height: 84px; }
}

/* The up/down nudges exist for touch, where a card cannot be dragged. With a mouse the card itself drags,
   so the buttons are just clutter beside every job. */
@media (hover: hover) and (pointer: fine) { .ty-order-btn { display: none; } }

/* ── The pin: "this view is my default". Pink (the pin token) so it matches Settings → My preferences. ──── */
.ty-pin { appearance: none; display: inline-flex; align-items: center; justify-content: center; width: 34px; height: 34px; margin-left: 6px; border-radius: 999px; border: 1.5px solid var(--ty-color-border-strong, #c2cad3); background: var(--ty-color-surface, #fff); color: var(--ty-color-text-subtle, #8a95a1); font-size: 15px; cursor: pointer; transition: transform .18s cubic-bezier(.34, 1.56, .64, 1), color .15s, border-color .15s, background .15s; vertical-align: middle; }
.ty-pin:hover { color: var(--ty-color-pin, #e0409a); border-color: var(--ty-color-pin, #e0409a); transform: rotate(-20deg) scale(1.08); }
.ty-pin.on { color: #fff; background: var(--ty-color-pin, #e0409a); border-color: var(--ty-color-pin, #e0409a); box-shadow: 0 6px 16px -8px var(--ty-color-pin, #e0409a); }
.ty-pin.on:hover { transform: scale(1.06); }

/* The crew a stop was routed to on the planning page (FB-055) — a quiet chip beside the assignee avatar,
   present only on a day that was actually shared out. */
.ty-crew {
    display: inline-flex; align-items: center; gap: 4px;
    padding: 1px 8px; border-radius: 999px; font: 600 11px var(--ty-font-base, inherit);
    background: var(--ty-color-primary-soft, #eef5fd); color: var(--ty-color-primary, #1b6ec2);
}
