/* Shell shared by the two proxy pages. Load /css/ui.css first — this file
   styles with its tokens.

     embed.html    bare frame, no chrome   (--bar stays 0)
     calculus.html frame + address bar     (--bar: 64px)

   The only structural difference between them is whether a bar sits above the
   frame, so that offset is one variable rather than two copies of the layout.

   Design note. On a proxy the address bar carries more weight than it does in
   a normal browser: every page is served from our own origin, so the chrome is
   the only thing that can tell you where you actually are. That makes the
   omnibox the one loud element here — origin in full ink, path stepped back,
   a scheme mark that reports the real scheme rather than always drawing a
   padlock. Everything around it is deliberately quiet. */

:root { --bar: 0px; }

html, body { height: 100%; overflow: hidden; }
body { background: var(--bg); }

.proxy-iframe {
  position: fixed;
  top: var(--bar);
  left: 0;
  width: 100%;
  height: calc(100vh - var(--bar));
  border: 0;
  /* White, not the page background: most sites assume a white canvas and
     paint no background of their own. */
  background: #fff;
  z-index: 1;
}

/* ── Address bar ──────────────────────────────────────────── */
/* Floats like the sidebar's groups do, but unlike them it reserves its space
   (via --bar) instead of overlaying — an address bar that covered the top of
   every page you visited would be worse than no address bar. */

.proxy-bar {
  position: fixed;
  top: 10px;
  left: 10px;
  right: 10px;
  height: 46px;
  z-index: 50;
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 0 8px;
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: 0;
  backdrop-filter: blur(20px);
  -webkit-backdrop-filter: blur(20px);
  box-shadow: var(--shadow);
  /* The progress filament is pinned to the bar's bottom edge. */
  overflow: hidden;
}

/* Hiding the bar zeroes --bar, so the frame grows into the space instead of
   leaving a gap where the bar was. Set on body, not :root, so it overrides the
   page's own :root value for everything inside. */
body.bar-hidden { --bar: 0px; }
body.bar-hidden .proxy-bar { display: none; }

/* Controls travel in two clusters, one at each end, so the omnibox reads as
   the centre of the bar rather than one more button in a row. */
.proxy-cluster { display: flex; align-items: center; gap: 2px; flex-shrink: 0; }

.proxy-btn {
  width: 32px;
  height: 32px;
  flex-shrink: 0;
  display: grid;
  place-items: center;
  border: 0;
  border-radius: 0;
  background: none;
  color: var(--text-dim);
  font: inherit;
  text-decoration: none;
  cursor: pointer;
  transition: background 0.14s ease, color 0.14s ease, opacity 0.14s ease;
}
.proxy-btn:hover { background: var(--surface-hover); color: var(--text); }
.proxy-btn svg { width: 17px; height: 17px; }
/* Back and forward go dim rather than vanishing when there is nowhere to go:
   a control that disappears makes the bar's width jump on every navigation. */
.proxy-btn[aria-disabled="true"] { opacity: 0.3; pointer-events: none; }

/* ── Omnibox ──────────────────────────────────────────────── */
/* Two layers over one pill: a display that reads well at a glance, and the
   real input, which only appears once you mean to type. Swapping them (rather
   than styling one input) is what allows the origin to be emphasised. */

.proxy-omni {
  position: relative;
  flex: 1;
  min-width: 0;
  display: flex;
  align-items: center;
  height: 34px;
  padding-left: 32px;
  border: 1px solid var(--line);
  border-radius: var(--radius-pill);
  background: rgba(0, 0, 0, 0.28);
  transition: border-color 0.14s ease, background 0.14s ease;
}
.proxy-omni:hover { background: rgba(0, 0, 0, 0.36); }
.proxy-omni:focus-within {
  border-color: rgba(255, 255, 255, 0.5);
  background: rgba(0, 0, 0, 0.42);
}

/* The scheme mark. Three honest states — a padlock drawn over http would be
   a lie, and this is exactly the screen where that matters. */
.proxy-scheme {
  position: absolute;
  left: 10px;
  display: grid;
  place-items: center;
  width: 16px;
  height: 16px;
  color: var(--text-faint);
  pointer-events: none;
}
.proxy-scheme svg { width: 13px; height: 13px; display: none; }
.proxy-scheme[data-state="secure"] .i-lock { display: block; color: rgba(255, 255, 255, 0.66); }
.proxy-scheme[data-state="insecure"] .i-warn { display: block; color: #fff; }
.proxy-scheme[data-state="blank"] .i-search { display: block; }

/* Display layer: a button, so it is reachable by keyboard and announces that
   clicking it does something. */
.proxy-display {
  flex: 1;
  min-width: 0;
  height: 100%;
  padding: 0 12px 0 0;
  border: 0;
  background: none;
  color: var(--text);
  font: inherit;
  font-size: 13.5px;
  text-align: left;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  cursor: text;
}
.proxy-display .u-origin { color: var(--text); }
.proxy-display .u-path { color: var(--text-faint); }
.proxy-display .u-placeholder { color: var(--text-faint); }

.proxy-url {
  position: absolute;
  inset: 0 0 0 32px;
  width: auto;
  padding: 0 12px 0 0;
  border: 0;
  background: none;
  color: var(--text);
  font: inherit;
  font-size: 13.5px;
  outline: none;
}
.proxy-url::placeholder { color: var(--text-faint); }

/* Only one of the two is ever present. */
.proxy-omni:not(.editing) .proxy-url { display: none; }
.proxy-omni.editing .proxy-display { display: none; }

/* ── Engine chip ──────────────────────────────────────────── */
/* Which backend is carrying this page. It is a readout, not a picker: the
   engine is a saved preference and Settings stays its single source of truth
   (see js/proxy.js). It earns its place because the two backends fail in
   completely different ways, and without this there is no way to tell from
   the page which one you are on. */

.proxy-engine {
  flex-shrink: 0;
  height: 22px;
  padding: 0 9px;
  display: grid;
  place-items: center;
  border: 1px solid var(--line);
  border-radius: var(--radius-pill);
  background: rgba(255, 255, 255, 0.04);
  color: var(--text-dim);
  font: inherit;
  font-size: 10.5px;
  font-weight: 600;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  text-decoration: none;
  white-space: nowrap;
  transition: color 0.14s ease, border-color 0.14s ease;
}
.proxy-engine:hover { color: var(--text); border-color: var(--line-strong); }

/* ── Progress filament ────────────────────────────────────── */
/* Replaces the full-screen curtain for every navigation after the first. A
   proxied page is slow enough that you want to see it arriving, and covering
   the previous page with a spinner for the whole wait told you less than a
   line that moves. */

.proxy-progress {
  position: absolute;
  left: 0;
  bottom: 0;
  height: 2px;
  width: 0;
  background: linear-gradient(90deg, rgba(255, 255, 255, 0.25), #fff);
  opacity: 0;
  transition: width 0.2s ease, opacity 0.25s ease;
  pointer-events: none;
}
.proxy-progress.active { opacity: 1; }

/* The handle that brings a hidden bar back. It only exists while the bar is
   hidden, and it has to sit above the frame to be clickable at all. Faint
   until pointed at, so it doesn't nag over the top of the site. */
.proxy-reveal {
  position: fixed;
  top: 0;
  left: 50%;
  transform: translateX(-50%);
  z-index: 60;
  display: none;
  place-items: center;
  width: 54px;
  height: 20px;
  padding: 0;
  border: 1px solid var(--line);
  border-top: 0;
  border-radius: 0;
  background: var(--surface);
  backdrop-filter: blur(20px);
  -webkit-backdrop-filter: blur(20px);
  color: var(--text-faint);
  cursor: pointer;
  opacity: 0.55;
  transition: opacity 0.14s ease, color 0.14s ease, height 0.14s ease;
}
body.bar-hidden .proxy-reveal { display: grid; }
.proxy-reveal:hover { opacity: 1; height: 24px; color: var(--text); }
.proxy-reveal svg { width: 15px; height: 15px; }

/* ── Loading and empty states ─────────────────────────────── */
/* The overlay is now only for a cold start, when the frame is empty and there
   is genuinely nothing behind it to look at. Once a page is up, navigation
   reports through the filament instead. */

.loading-overlay,
.empty-state {
  position: fixed;
  top: var(--bar);
  left: 0;
  width: 100%;
  height: calc(100vh - var(--bar));
  display: none;
  align-items: center;
  justify-content: center;
  background:
    radial-gradient(700px 400px at 30% 20%, rgba(255, 255, 255, 0.07), transparent 60%),
    radial-gradient(600px 400px at 70% 80%, rgba(255, 255, 255, 0.05), transparent 60%),
    var(--bg);
}
.loading-overlay { z-index: 20; transition: opacity 0.4s ease; }
.empty-state { z-index: 19; }

#loading-container,
.empty-content {
  padding: clamp(28px, 5vw, 44px);
  text-align: center;
}

.loader {
  width: 44px;
  height: 44px;
  margin: 0 auto 22px;
  border: 3px solid rgba(255, 255, 255, 0.14);
  border-top-color: var(--sky);
  border-radius: 50%;
  animation: proxy-spin 0.8s linear infinite;
}
@keyframes proxy-spin { to { transform: rotate(360deg); } }

#theh1, .empty-title {
  font-size: 19px;
  font-weight: 600;
  letter-spacing: -0.01em;
  margin-bottom: 8px;
}
#thep, .empty-subtitle {
  max-width: 46ch;
  margin: 0 auto;
  color: var(--text-dim);
  font-size: 14px;
  line-height: 1.6;
}

/* The destination, shown while it is being fetched. On a slow school
   connection this is the difference between "it's broken" and "it's working
   on it", and it is the one fact the user cannot otherwise see yet. */
.loading-target {
  display: inline-block;
  max-width: 42ch;
  margin-top: 14px;
  padding: 5px 12px;
  border: 1px solid var(--line);
  border-radius: var(--radius-pill);
  background: rgba(255, 255, 255, 0.04);
  color: var(--text-dim);
  font-size: 12.5px;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  vertical-align: bottom;
}
.loading-target:empty { display: none; }

.loading-dots { display: inline-flex; gap: 4px; margin-left: 5px; vertical-align: middle; }
.loading-dots span {
  width: 4px;
  height: 4px;
  border-radius: 50%;
  background: var(--sky);
  animation: proxy-dot 1.4s infinite ease-in-out;
}
.loading-dots span:nth-child(2) { animation-delay: 0.2s; }
.loading-dots span:nth-child(3) { animation-delay: 0.4s; }
@keyframes proxy-dot {
  0%, 80%, 100% { opacity: 0.25; transform: scale(0.8); }
  40% { opacity: 1; transform: scale(1); }
}

.empty-icon {
  width: 62px;
  height: 62px;
  margin: 0 auto 18px;
  display: grid;
  place-items: center;
  border: 1px solid var(--line);
  border-radius: 0;
  background: var(--surface-raised);
}
.empty-icon svg { width: 30px; height: 30px; color: var(--sky); }

.empty-actions { display: flex; justify-content: center; gap: 8px; margin-top: 18px; }

/* A keyboard hint, shown once on the browser's empty state. Ctrl+L is the one
   shortcut worth teaching here, because the omnibox is the whole point. */
.empty-hint {
  margin-top: 20px;
  color: var(--text-faint);
  font-size: 12.5px;
}
.empty-hint kbd {
  padding: 2px 6px;
  border: 1px solid var(--line);
  border-radius: 0;
  background: rgba(255, 255, 255, 0.05);
  font: inherit;
  font-size: 11px;
}

@media (prefers-reduced-motion: reduce) {
  .loader, .loading-dots span { animation: none; }
  .proxy-progress { transition: opacity 0.25s ease; }
}

@media (max-width: 720px) {
  /* The engine readout is the first thing to go: it is diagnostic, and the
     omnibox needs the room more than it does. */
  .proxy-engine { display: none; }
}

@media (max-width: 600px) {
  .proxy-bar { gap: 4px; padding: 0 6px; }
  .proxy-cluster { gap: 0; }
  /* Forward is the least-used control, and fullscreen has a gesture on
     touch — the address needs the width more than either. */
  #forward-btn, #fullscreen-btn { display: none; }
  .proxy-btn { width: 30px; height: 30px; }
}
