/* ============================================================
   Pipezoom - css/shell.css, the frame around every page.

   The rail down the left with its brand row, the double arrow that
   collapses it, its nested menus and their flyout, the top bar with the
   phone's burger, the search and the right-hand group, the crumbs, the
   Stuck sheet and the account panel. base.css defines the tokens these
   rules read, the rail's 2 widths among them (rail-full, rail-icons).
   Loaded by the css/base.css set in includes/manifest.php.
   Notes: docs/notes/app.pipezoom.com/css/shell.css.md
   ============================================================ */

/* Sidebar */
.sidebar{
  position:fixed;
  top:0;left:0;bottom:0;
  width:var(--sidebar-w);
  background:var(--shell-bg);
  border-right:1px solid var(--shell-line);
  display:flex;
  flex-direction:column;
  z-index:60;
  transform:translateX(-100%);
  transition:transform .2s ease;
  overflow-y:auto;
  -webkit-overflow-scrolling:touch;
  /* Scrolls with no visible scrollbar. */
  scrollbar-width:none;
  -ms-overflow-style:none;
}
.sidebar::-webkit-scrollbar{display:none;width:0;height:0;}
.sidebar.open{transform:translateX(0);box-shadow:var(--shadow-drawer);}

/* The brand row is the top bar's height, and the 2 rules under them form
   1 line. It stays at the top while a long rail scrolls under it. */
.side-brand{
  position:sticky;top:0;z-index:1;
  display:flex;align-items:center;
  flex-shrink:0;
  height:var(--topbar-h);
  margin-bottom:10px;
  padding:0 14px;
  background:inherit;
  border-bottom:1px solid var(--shell-line);
}
.side-logo{display:inline-flex;align-items:center;padding:4px 8px;border-radius:var(--radius-sm);}
.side-logo img{display:block;height:36px;width:auto;}
.side-mark{display:none;width:28px;height:28px;}
/* The logo's wordmark is white. White is the 1 theme with a pale rail, and
   there the tile behind the logo takes the shell's ink. */
[data-theme="white"] .side-logo{background:var(--shell-ink);}

/* The width switch: the double arrow at the right end of the line under
   the brand. Anchored to a zero-height box, so the rail loses no height
   to it while expanded; collapsed, the box takes a row of its own so the
   marks under it keep their clearance. */
.side-rail{position:relative;height:0;flex-shrink:0;}
.side-rail-btn{
  position:absolute;
  top:-4px;right:8px;
  display:inline-flex;align-items:center;justify-content:center;
  width:28px;height:28px;
  border-radius:var(--radius-sm);
  border:0;
  background:transparent;
  color:var(--shell-ink-faint);
  font-size:.78rem;
  cursor:pointer;
}
.side-rail-btn:hover{background:var(--shell-raised);color:var(--shell-ink);}
.side-rail-btn:focus-visible{outline:2px solid var(--accent);outline-offset:1px;}
.rail-out{display:none;}
:root[data-rail="on"] .rail-in{display:none;}
:root[data-rail="on"] .rail-out{display:inline-flex;}
@media (max-width:899px){
  .side-rail{display:none;}
}

.side-nav{display:flex;flex-direction:column;gap:1px;padding:0 8px 16px;}

/* A nested menu: a press that reads as a row, its rows under it, each
   inset by the icon's width so the menu reads as 1 block. */
.side-menu{display:flex;flex-direction:column;gap:1px;}
.side-menu-btn{
  width:100%;
  border:0;background:transparent;
  font:inherit;text-align:left;
  cursor:pointer;
}
.side-menu-car{
  margin-left:auto;
  font-size:.68rem;
  color:var(--shell-ink-faint);
  transition:transform .15s;
}
.side-menu-btn[aria-expanded="true"] .side-menu-car{transform:rotate(180deg);}
.side-menu-list{display:flex;flex-direction:column;gap:1px;padding:2px 0 6px;}
.side-menu-list[hidden]{display:none;}
.side-item.side-sub{padding:7px 11px 7px 22px;font-size:.88rem;}

/* The hairline between the rail's blocks: the top rows, Calendar, Account, Admin, Add-ons. */
.side-sep{height:1px;margin:6px 3px;background:var(--shell-line);flex-shrink:0;}

/* Schedule inside Calendar: the link to the board with a chevron beside it,
   and Week and Day under it, inset a second step. */
.side-sched{display:flex;flex-direction:column;gap:1px;}
.side-sched-row{display:flex;align-items:stretch;gap:2px;}
.side-sched-go{flex:1;min-width:0;}
.side-sched-btn{
  flex-shrink:0;width:30px;
  border:0;border-radius:var(--radius-sm);background:transparent;
  color:var(--shell-ink-faint);font-size:.68rem;cursor:pointer;
}
.side-sched-btn:hover{background:var(--shell-raised);color:var(--shell-ink);}
.side-sched-btn:focus-visible{outline:2px solid var(--accent);outline-offset:-2px;}
.side-sched-btn i{transition:transform .15s;}
.side-sched-btn[aria-expanded="true"] i{transform:rotate(180deg);}
.side-sched-list{display:flex;flex-direction:column;gap:1px;}
.side-sched-list[hidden]{display:none;}
.side-item.side-sub2{padding-left:44px;}
.side-out{margin:0;}
.side-out-btn{width:100%;border:0;background:transparent;font:inherit;text-align:left;cursor:pointer;}

/* The flyout: the rows of 1 menu beside the collapsed rail, at the
   menu's own height, on the overlay surface (js/sidemenu.js places it). */
.side-fly{
  position:fixed;
  z-index:70;
  min-width:220px;
  padding:6px;
  background:var(--surface-high);
  border:1px solid var(--line-strong);
  border-radius:var(--radius);
  box-shadow:var(--shadow-overlay);
}
.side-fly[hidden]{display:none;}
.side-fly-t{
  padding:6px 10px 4px;
  font-size:.66rem;font-weight:700;letter-spacing:.9px;text-transform:uppercase;
  color:var(--ink-faint);
}
.side-fly .side-item{color:var(--ink);padding:8px 10px;}
.side-fly .side-item:hover{background:var(--surface-hover);color:var(--ink);}
.side-fly .side-item.active{background:var(--accent-strong);color:var(--ink-inverse);}
.side-fly .side-out-btn{color:var(--ink);}
/* The flyout shows Week and Day under Schedule with no chevron. */
.side-fly .side-sched-btn{display:none;}
.side-fly .side-sched-list[hidden]{display:flex;}
.side-fly .side-sub2{padding-left:26px;}

/* The group headings name each block of rows in small capitals. */
.side-group{
  font-size:.66rem;font-weight:700;letter-spacing:.9px;text-transform:uppercase;
  color:var(--shell-ink-faint);
  padding:14px 11px 5px;
}
.side-group:first-child{padding-top:2px;}
.side-item{
  display:flex;align-items:center;gap:11px;
  padding:9px 11px;
  border-radius:var(--radius-sm);
  color:var(--shell-ink-faint);
  font-size:.92rem;
  font-weight:500;
  transition:background .12s,color .12s;
}
.side-item:hover{background:var(--shell-raised);color:var(--shell-ink);text-decoration:none;}

/* The active item is filled and marks the current page from across a
   phone screen. */
.side-item.active{background:var(--accent-strong);color:var(--ink-inverse);font-weight:600;}
.side-item.active:hover{background:var(--accent-hover);color:var(--ink-inverse);}
.side-item.active .side-ic{color:var(--ink-inverse);}
.side-ic{width:18px;flex-shrink:0;text-align:center;font-size:.95rem;}

.backdrop{position:fixed;inset:0;background:var(--scrim);z-index:55;}

/* Top bar: the burger, the search, then the right-hand group. */
.topbar{
  position:sticky;
  top:0;
  z-index:50;
  display:flex;
  align-items:center;
  gap:8px;
  height:var(--topbar-h);
  padding:0 10px;
  background:var(--shell-veil);
  backdrop-filter:blur(8px);
  border-bottom:1px solid var(--shell-line);
}
.icon-btn{
  display:flex;align-items:center;justify-content:center;
  width:38px;height:38px;
  border-radius:var(--radius-sm);
  color:var(--shell-ink-soft);
  flex-shrink:0;
}
.icon-btn:hover{background:var(--shell-raised);color:var(--shell-ink);}
.icon-btn svg{width:21px;height:21px;}
.burger i{font-size:1.1rem;}
/* The theme picker, the hand, the bell and the account, held at the right
   end of the bar with or without a search beside them. */
.topbar-end{display:flex;align-items:center;gap:inherit;flex-shrink:0;margin-left:auto;}

/* Breadcrumbs
   The slot under the top bar names the current page. Because the chip
   row inside the page switches sections, the crumbs carry no navigation
   beyond the step back to the whole page. */
.crumbs{
  position:sticky;
  top:var(--topbar-h);
  z-index:45;
  display:flex;
  gap:8px;
  align-items:center;
  min-height:38px;
  padding:0 16px;
  overflow-x:auto;
  overflow-y:hidden;
  scrollbar-width:none;
  background:var(--shell-veil);
  backdrop-filter:blur(8px);
  border-bottom:1px solid var(--shell-line);
  font-size:.82rem;
}
.crumbs::-webkit-scrollbar{display:none;}
.crumb{
  flex:0 0 auto;
  color:var(--shell-ink-faint);
  white-space:nowrap;
}
a.crumb:hover{color:var(--shell-ink);text-decoration:none;}
.crumb-now{color:var(--shell-ink);font-weight:600;}
.crumb-sep{
  flex:0 0 auto;
  color:var(--shell-ink-faint);
  font-size:.68rem;
  opacity:.7;
}

@media (min-width:1080px){
  .crumbs{padding:0 22px;}
}

/* Today's chips, in the sticky slot: the same row, with chips at the
   trail's position. Because the slot is on the dark bar's background on
   every theme, the chips wear the shell palette. */
.crumbchips{gap:6px;min-height:42px;}
.crumbchips a{
  flex:0 0 auto;
  padding:5px 12px;
  border-radius:var(--radius-pill);
  border:1px solid var(--shell-line);
  color:var(--shell-ink-soft);
  font-size:.8rem;
  font-weight:600;
  white-space:nowrap;
  transition:background .12s,color .12s,border-color .12s;
}
.crumbchips a:hover{
  background:var(--accent-strong);
  border-color:var(--accent-strong);
  color:var(--ink-inverse);
  text-decoration:none;
}
.crumbchips a.accent{
  background:var(--accent-strong);
  border-color:var(--accent-strong);
  color:var(--ink-inverse);
}
.crumbchips a.accent:hover{background:var(--accent-hover);border-color:var(--accent-hover);}

/* Search
   The fastest route to any fact on this site takes the middle of the bar. */
.topbar-search{position:relative;flex:1;min-width:0;}
.search-ic{
  position:absolute;
  left:10px;top:50%;
  transform:translateY(-50%);
  width:16px;height:16px;
  color:var(--shell-ink-faint);
  pointer-events:none;
}
#searchInput{
  width:100%;
  background:var(--shell-raised);
  border:1px solid var(--shell-line);
  border-radius:var(--radius);
  color:var(--shell-ink);
  padding:8px 12px 8px 33px;
  font-size:.91rem;
  outline:none;
}
#searchInput::placeholder{color:var(--shell-ink-faint);}
#searchInput:focus{border-color:var(--accent);box-shadow:0 0 0 3px var(--accent-ring-soft);}

.search-results{
  position:absolute;
  top:calc(100% + 6px);
  left:0;right:0;
  background:var(--surface-high);
  border:1px solid var(--line-strong);
  border-radius:var(--radius);
  max-height:min(64vh,440px);
  overflow-y:auto;
  box-shadow:var(--shadow-overlay);
}
.sr-group{
  padding:9px 12px 3px;
  font-size:.67rem;
  font-weight:700;
  text-transform:uppercase;
  letter-spacing:.7px;
  color:var(--ink-faint);
}
.sr-item{display:block;padding:9px 12px;color:var(--ink);font-size:.9rem;}
.sr-item .sr-d{
  color:var(--ink-faint);
  font-size:.78rem;
  display:block;
  white-space:nowrap;
  overflow:hidden;
  text-overflow:ellipsis;
}
.sr-item:hover,.sr-item.sel{background:var(--surface-hover);text-decoration:none;}
.sr-empty{padding:14px 12px;color:var(--ink-faint);font-size:.88rem;}

/* Stuck
   The job holds more facets than working memory can carry, and an
   overloaded rep freezes. Because the effort of going to look is the
   thing that has run out, this is 1 tap from every screen, asks for no
   category before helping, and ends in a phone number or 2 clicks. */
.stuck-btn{
  display:flex;align-items:center;gap:7px;
  flex-shrink:0;
  padding:7px 12px;
  border-radius:var(--radius);
  background:var(--accent-strong);
  color:var(--ink-inverse);
  font-size:.88rem;
  font-weight:700;
}
.stuck-btn:hover{background:var(--accent-hover);}
.stuck-btn i{font-size:.9rem;}

.stuck-sheet{
  position:fixed;inset:0;
  z-index:80;
  background:var(--scrim);
  display:flex;
  align-items:flex-start;
  justify-content:center;
  padding:14px;
  overflow-y:auto;
  -webkit-overflow-scrolling:touch;
}

/* Because an author display rule beats the browser's
   [hidden]{display:none}, any element both hidden by attribute and given
   a display value needs its own [hidden] rule. */
.stuck-sheet[hidden]{display:none;}

body.stuck-open{overflow:hidden;}

.stuck-panel{
  width:100%;
  max-width:620px;
  margin-top:6vh;
  background:var(--surface-high);
  border:1px solid var(--line-strong);
  border-radius:var(--radius);
  box-shadow:var(--shadow-overlay);
  padding:15px;
}
.stuck-head{display:flex;align-items:center;gap:10px;margin-bottom:12px;}
.stuck-title{font-size:1.12rem;font-weight:700;flex:1;}

.stuck-search{position:relative;}
.stuck-ic{
  position:absolute;left:12px;top:50%;transform:translateY(-50%);
  color:var(--ink-faint);font-size:.92rem;pointer-events:none;
}
#stuckInput{
  width:100%;
  background:var(--surface-page);
  border:1px solid var(--line-strong);
  border-radius:var(--radius);
  color:var(--ink);
  padding:12px 13px 12px 37px;
  font-size:1rem;
  outline:none;
}
#stuckInput::placeholder{color:var(--ink-faint);}
#stuckInput:focus{border-color:var(--accent);box-shadow:0 0 0 3px var(--accent-ring-soft);}

/* Because picking from 6 costs less than composing a search, these are
   offered before any typing. */
.stuck-quick{display:flex;flex-wrap:wrap;gap:6px;margin-top:10px;}
.stuck-quick[hidden]{display:none;}
.stuck-chip{
  border:1px solid var(--line-strong);
  border-radius:var(--radius-pill);
  padding:7px 13px;
  font-size:.83rem;
  font-weight:600;
  color:var(--ink);
  background:var(--surface-raised);
}
.stuck-chip:hover{border-color:var(--line-strong);background:var(--surface-hover);}

.stuck-list{display:flex;flex-direction:column;gap:7px;margin-top:12px;}

/* The floor of the panel. Because calls need no decision and every other
   activity depends on them, calls are the answer once nothing fits or
   the choice itself is the blocker. */
.stuck-floor{
  margin-top:14px;
  padding-top:14px;
  border-top:1px solid var(--line);
}
.stuck-floor-label{
  font-size:.68rem;font-weight:700;letter-spacing:.8px;text-transform:uppercase;
  color:var(--ink-faint);
}
.stuck-floor-text{color:var(--ink-soft);font-size:.88rem;line-height:1.55;margin-top:5px;}
.stuck-floor-go{
  display:inline-flex;align-items:center;gap:8px;
  margin-top:10px;
  background:var(--accent-strong);
  color:var(--ink-inverse);
  font-weight:700;font-size:.92rem;
  padding:11px 15px;
  border-radius:var(--radius-sm);
}
.stuck-floor-go:hover{background:var(--accent-hover);text-decoration:none;}

@media (max-width:520px){
  .stuck-btn-text{display:none;}
  .stuck-btn{padding:7px 10px;}
  .stuck-panel{margin-top:0;}
}

/* Account panel */
.auth-area{position:relative;flex-shrink:0;}
.auth-btn{
  display:flex;align-items:center;gap:7px;
  padding:7px 10px;
  border-radius:var(--radius);
  border:1px solid var(--shell-line);
  color:var(--shell-ink);
  font-size:.89rem;
  max-width:190px;
}
.auth-btn:hover{background:var(--shell-raised);}
.auth-name{white-space:nowrap;overflow:hidden;text-overflow:ellipsis;}
.chev{width:13px;height:13px;color:var(--shell-ink-faint);flex-shrink:0;}

.auth-pop{
  position:absolute;
  top:calc(100% + 8px);
  right:0;
  width:min(280px,calc(100vw - 24px));
  background:var(--surface-high);
  border:1px solid var(--line-strong);
  border-radius:var(--radius);
  padding:9px;
  box-shadow:var(--shadow-overlay);
  z-index:70;
}
.pop-link{
  display:block;
  width:100%;
  text-align:left;
  padding:9px 10px;
  border-radius:var(--radius-sm);
  color:var(--ink);
  font-size:.9rem;
}
.pop-link:hover{background:var(--surface-hover);text-decoration:none;}

/* Tablet */
@media (min-width:640px){
  .topbar{padding:0 16px;gap:10px;}
  .topbar-search{max-width:460px;}
}

/* Desktop: the rail is pinned open, and the double arrow under the brand
   is its width switch; the burger is the phone's control alone. */
@media (min-width:900px){
  .sidebar{transform:none;box-shadow:none;}
  .content{margin-left:var(--sidebar-w);}
  .burger{display:none;}
  .backdrop{display:none !important;}
  .topbar{padding:0 22px;}
  .topbar-search{max-width:520px;}
}

/* Small phones */
@media (max-width:400px){
  .auth-name{display:none;}
  .auth-btn{padding:7px;}
  .chev{display:none;}
}

/* The rail, collapsed
   The rows show their marks alone, and about a third of the rail's width
   returns to the page. 1 token, sidebar-w, moves the rail, the content
   margin, the top bar and the breadcrumb row inside it together. The
   brand row shows the mark alone, the group headings become hairlines at
   their own positions, and js/rail.js puts each row's name on its title.
   The rail is a drawer under 900px, and these rules apply above it. */
@media (min-width:900px){
  :root[data-rail="on"]{--sidebar-w:var(--rail-icons);}
  :root[data-rail="on"] .side-brand{justify-content:center;padding:0;margin-bottom:0;}
  :root[data-rail="on"] .side-logo{display:none;}
  :root[data-rail="on"] .side-mark{display:block;}
  /* Collapsed, the switch takes a row of its own, centered over the marks. */
  :root[data-rail="on"] .side-rail{height:34px;}
  :root[data-rail="on"] .side-rail-btn{top:3px;right:50%;transform:translateX(50%);}
  :root[data-rail="on"] .side-nav{padding:0 8px 16px;}
  /* Scoped to the rail: the flyout's rows keep their names. */
  :root[data-rail="on"] .side-nav .side-item{justify-content:center;gap:0;padding:11px 0;}
  :root[data-rail="on"] .side-nav .side-item span,
  :root[data-rail="on"] .side-menu-car{display:none;}
  /* A menu's rows are not drawn in the rail: the icon opens them beside it. */
  :root[data-rail="on"] .side-menu-list{display:none;}
  /* A menu holding the current page shows it on the press itself. */
  :root[data-rail="on"] .side-menu-on > .side-menu-btn{background:var(--shell-raised);color:var(--shell-ink);}
}

/* Signed out
   The sign-in and register pages have no rail: the content spans the
   window and the top bar holds the logo in the rail's place. */
.layout-out .content{margin-left:0;}
.topbar-brand{display:flex;align-items:center;margin-right:auto;}
.topbar-brand img{height:36px;width:auto;display:block;}
