diff --git a/fe/index.html b/fe/index.html
index 82fe2c8..b9f9387 100644
--- a/fe/index.html
+++ b/fe/index.html
@@ -1,32 +1,65 @@
-
-
-
-
-
-
-
-
- mitlist
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+ mitlist
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/fe/src/App.vue b/fe/src/App.vue
index 18233c3..b343612 100644
--- a/fe/src/App.vue
+++ b/fe/src/App.vue
@@ -18,7 +18,8 @@ body {
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
color: #2c3e50;
- background-color: #f0f2f5; /* Example background */
+ background-color: #f0f2f5;
+ /* Example background */
}
#app {
diff --git a/fe/src/assets/valerie-ui.scss b/fe/src/assets/valerie-ui.scss
index a56ea41..85e05ed 100644
--- a/fe/src/assets/valerie-ui.scss
+++ b/fe/src/assets/valerie-ui.scss
@@ -1,737 +1,1728 @@
+:root {
+ /* Colors */
+ --primary: #ff7b54;
+ --secondary: #ffb26b;
+ --accent: #ffd56b;
+ /* Yellow - for sticky notes */
+ --secondary-accent: #54c7ff;
+ /* Light Blue - for contrast */
+ --danger: #ff4d4d;
+ --success: #a0e7a0;
+ --warning: var(--accent);
+ --dark: #393e46;
+ --light: #fff8f0;
+ --black: #000000;
- :root {
- /* Colors */
- --primary: #ff7b54;
- --secondary: #ffb26b;
- --accent: #ffd56b; /* Yellow - for sticky notes */
- --secondary-accent: #54c7ff; /* Light Blue - for contrast */
- --danger: #ff4d4d;
- --success: #a0e7a0;
- --warning: var(--accent);
- --dark: #393e46;
- --light: #fff8f0;
- --black: #000000;
+ /* Shadows & Borders */
+ --shadow-lg: 8px 8px 0px var(--black);
+ --shadow-md: 6px 6px 0px var(--black);
+ --shadow-sm: 3px 3px 0px var(--black);
+ --shadow-inset: inset 2px 2px 1px rgba(0, 0, 0, 0.15);
+ --border-width: 3px;
+ --border-style: solid;
+ --border-color: var(--black);
+ --border: var(--border-width) var(--border-style) var(--border-color);
- /* Shadows & Borders */
- --shadow-lg: 8px 8px 0px var(--black);
- --shadow-md: 6px 6px 0px var(--black);
- --shadow-sm: 3px 3px 0px var(--black);
- --shadow-inset: inset 2px 2px 1px rgba(0, 0, 0, 0.15);
- --border-width: 3px;
- --border-style: solid;
- --border-color: var(--black);
- --border: var(--border-width) var(--border-style) var(--border-color);
+ /* Transitions */
+ --transition-speed: 0.25s;
+ --transition-speed-fast: 0.1s;
+ --transition-ease-out: ease-out;
+ --transition-press: cubic-bezier(0.34, 1.56, 0.64, 1);
- /* Transitions */
- --transition-speed: 0.25s;
- --transition-speed-fast: 0.1s;
- --transition-ease-out: ease-out;
- --transition-press: cubic-bezier(0.34, 1.56, 0.64, 1);
+ /* Focus */
+ --focus-outline-color: var(--secondary-accent);
+ --focus-outline-width: 3px;
+ --focus-outline-offset: 2px;
+ --focus-outline: var(--focus-outline-width) solid var(--focus-outline-color);
- /* Focus */
- --focus-outline-color: var(--secondary-accent);
- --focus-outline-width: 3px;
- --focus-outline-offset: 2px;
- --focus-outline: var(--focus-outline-width) solid
- var(--focus-outline-color);
+ /* Textures */
+ --paper-texture: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='60' height='60' viewBox='0 0 60 60'%3E%3Cg fill-rule='evenodd'%3E%3Cg fill='%23a59a8a' fill-opacity='0.15'%3E%3Cpath opacity='.5' d='M36 60v-6h6v6h-6zm18-12v-6h6v6h-6zM6 0v6H0V0h6zM6 12v6H0v-6h6zM18 0v6h-6V0h6zM18 12v6h-6v-6h6zM30 0v6h-6V0h6zM30 12v6h-6v-6h6zM42 0v6h-6V0h6zM42 12v6h-6v-6h6zM54 0v6h-6V0h6zM54 12v6h-6v-6h6zM6 24v6H0v-6h6zM6 36v6H0v-6h6zM6 48v6H0v-6h6zM18 24v6h-6v-6h6zM18 36v6h-6v-6h6zM18 48v6h-6v-6h6zM30 24v6h-6v-6h6zM30 36v6h-6v-6h6zM30 48v6h-6v-6h6zM42 24v6h-6v-6h6zM42 36v6h-6v-6h6zM42 48v6h-6v-6h6zM54 24v6h-6v-6h6zM54 36v6h-6v-6h6zM54 48v6h-6v-6h6z'/%3E%3C/g%3E%3C/g%3E%3C/svg%3E");
+ --progress-texture: repeating-linear-gradient(45deg,
+ rgba(0, 0, 0, 0.05),
+ rgba(0, 0, 0, 0.05) 5px,
+ transparent 5px,
+ transparent 10px);
+}
- /* Textures */
- --paper-texture: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='60' height='60' viewBox='0 0 60 60'%3E%3Cg fill-rule='evenodd'%3E%3Cg fill='%23a59a8a' fill-opacity='0.15'%3E%3Cpath opacity='.5' d='M36 60v-6h6v6h-6zm18-12v-6h6v6h-6zM6 0v6H0V0h6zM6 12v6H0v-6h6zM18 0v6h-6V0h6zM18 12v6h-6v-6h6zM30 0v6h-6V0h6zM30 12v6h-6v-6h6zM42 0v6h-6V0h6zM42 12v6h-6v-6h6zM54 0v6h-6V0h6zM54 12v6h-6v-6h6zM6 24v6H0v-6h6zM6 36v6H0v-6h6zM6 48v6H0v-6h6zM18 24v6h-6v-6h6zM18 36v6h-6v-6h6zM18 48v6h-6v-6h6zM30 24v6h-6v-6h6zM30 36v6h-6v-6h6zM30 48v6h-6v-6h6zM42 24v6h-6v-6h6zM42 36v6h-6v-6h6zM42 48v6h-6v-6h6zM54 24v6h-6v-6h6zM54 36v6h-6v-6h6zM54 48v6h-6v-6h6z'/%3E%3C/g%3E%3C/g%3E%3C/svg%3E");
- --progress-texture: repeating-linear-gradient(
- 45deg,
- rgba(0, 0, 0, 0.05),
- rgba(0, 0, 0, 0.05) 5px,
- transparent 5px,
- transparent 10px
- );
- }
+/* Accessibility Helpers */
+.sr-only {
+ position: absolute;
+ width: 1px;
+ height: 1px;
+ padding: 0;
+ margin: -1px;
+ overflow: hidden;
+ clip: rect(0, 0, 0, 0);
+ white-space: nowrap;
+ border: 0;
+}
- /* Accessibility Helpers */
- .sr-only {
- position: absolute;
- width: 1px;
- height: 1px;
- padding: 0;
- margin: -1px;
- overflow: hidden;
- clip: rect(0, 0, 0, 0);
- white-space: nowrap;
- border: 0;
- }
+/* Reduced Motion Preference */
+@media (prefers-reduced-motion: reduce) {
- /* Reduced Motion Preference */
- @media (prefers-reduced-motion: reduce) {
- *,
- *::before,
- *::after {
- animation-duration: 0.01ms !important;
- animation-iteration-count: 1 !important;
- transition-duration: 0.01ms !important;
- scroll-behavior: auto !important;
- transition-delay: 0ms !important;
- }
- }
+ *,
+ *::before,
+ *::after {
+ animation-duration: 0.01ms !important;
+ animation-iteration-count: 1 !important;
+ transition-duration: 0.01ms !important;
+ scroll-behavior: auto !important;
+ transition-delay: 0ms !important;
+ }
+}
- /* Basic Reset & Body */
- *,
- *::before,
- *::after {
- box-sizing: border-box;
- }
- body {
- font-family: "Patrick Hand", cursive;
- background-color: var(--light);
- background-image: var(--paper-texture);
- padding: 2rem 1rem;
- color: var(--dark);
- font-size: 1.1rem;
- line-height: 1.6;
- overflow-x: hidden; /* Prevent horizontal scroll */
- margin: 0;
- }
- .container {
- max-width: 1000px;
- margin: 0 auto;
- }
+/* Basic Reset & Body */
+*,
+*::before,
+*::after {
+ box-sizing: border-box;
+}
- /* Focus Visible Styles */
- :is(a, button, input, select, textarea, [tabindex]):not(
- [tabindex="-1"]
- ):focus-visible {
- outline: var(--focus-outline);
- outline-offset: var(--focus-outline-offset);
- box-shadow: 0 0 0 var(--focus-outline-width) var(--focus-outline-color),
- var(--shadow-md);
- z-index: 10; /* Bring focused element forward */
- }
- .btn:focus-visible {
- box-shadow: 0 0 0 var(--focus-outline-width) var(--focus-outline-color),
- var(--shadow-lg);
- }
- .form-input:focus-visible {
- box-shadow: var(--shadow-inset),
- 0 0 0 var(--focus-outline-width) var(--focus-outline-color),
- var(--shadow-sm);
- }
- .list-item:focus-visible { /* Focus on list item might need adjustment if using swipe */
- outline-offset: -var(--border-width);
- z-index: 10;
- }
- .tab-item:focus-visible {
- outline-offset: 4px;
- z-index: 5; /* Higher than non-focused tabs */
- }
- .checkbox-label input:focus-visible ~ .checkmark,
- .radio-label input:focus-visible ~ .checkmark {
- outline: var(--focus-outline);
- outline-offset: var(--focus-outline-offset);
- box-shadow: var(--shadow-sm),
- 0 0 0 var(--focus-outline-width) var(--focus-outline-color);
- }
- .switch-container input:focus-visible + .switch {
- outline: var(--focus-outline);
- outline-offset: var(--focus-outline-offset);
- }
- .avatar:focus-visible {
- box-shadow: 0 0 0 var(--focus-outline-width) var(--focus-outline-color),
- var(--shadow-sm);
- }
- .tooltip .tooltip-trigger:focus-visible {
- outline: var(--focus-outline);
- outline-offset: var(--focus-outline-offset);
- }
+body {
+ font-family: "Patrick Hand", cursive;
+ background-color: var(--light);
+ background-image: var(--paper-texture);
+ // padding: 2rem 1rem;s
+ color: var(--dark);
+ font-size: 1.1rem;
+ line-height: 1.6;
+ overflow-x: hidden;
+ /* Prevent horizontal scroll */
+ margin: 0;
+}
- /* Headings */
- h1,
- h2,
- h3 {
- font-weight: bold;
- color: var(--dark);
- text-transform: uppercase;
- letter-spacing: 1.5px;
- position: relative;
- display: inline-block;
- margin-bottom: 1.5rem;
- padding-bottom: 8px;
- }
- h1::after,
- h2::after,
- h3::after {
- content: "";
- position: absolute;
- bottom: 0;
- left: 0;
- width: 100%;
- height: var(--border-width);
- background-color: var(--primary);
- box-shadow: var(--shadow-sm);
- }
- h1 { font-size: clamp(2rem, 5vw, 2.5rem); }
- h2 { font-size: clamp(1.6rem, 4vw, 2rem); }
- h3 { font-size: clamp(1.3rem, 3.5vw, 1.5rem); }
+.container {
+ max-width: 1000px;
+ margin: 0 auto;
+}
- /* Icon Base Style */
- .icon {
- display: inline-block;
- width: 1.1em;
- height: 1.1em;
- vertical-align: -0.15em;
- margin-right: 0.4em;
- fill: currentColor;
- }
- .btn .icon { margin-right: 0.5em; }
- button > .icon:last-child { margin-right: 0; }
- .icon-sm { width: 0.9em; height: 0.9em; }
- .icon-lg { width: 1.5em; height: 1.5em; }
+/* Focus Visible Styles */
+:is(a, button, input, select, textarea, [tabindex]):not([tabindex="-1"]):focus-visible {
+ outline: var(--focus-outline);
+ outline-offset: var(--focus-outline-offset);
+ box-shadow: 0 0 0 var(--focus-outline-width) var(--focus-outline-color),
+ var(--shadow-md);
+ z-index: 10;
+ /* Bring focused element forward */
+}
- /* Buttons */
- .btn {
- background-color: var(--primary);
- color: var(--dark);
- border: var(--border);
- font-family: inherit;
- font-size: 1rem;
- font-weight: bold;
- padding: 0.8rem 1.6rem;
- cursor: pointer;
- box-shadow: var(--shadow-md);
- transition: transform var(--transition-speed) var(--transition-ease-out),
- box-shadow var(--transition-speed) var(--transition-ease-out),
- background-color var(--transition-speed) var(--transition-ease-out);
- position: relative;
- text-transform: uppercase;
- letter-spacing: 1px;
- margin: 0.5rem;
- display: inline-flex;
- align-items: center;
- justify-content: center;
- text-decoration: none;
- text-align: center;
- touch-action: manipulation;
- overflow: hidden;
- }
- .btn:hover:not(:disabled) {
- transform: translate(-3px, -3px);
- box-shadow: var(--shadow-lg);
- }
- .btn:active:not(:disabled) {
- transform: translate(2px, 2px) scale(0.98);
- box-shadow: var(--shadow-sm);
- transition-duration: var(--transition-speed-fast);
- transition-timing-function: var(--transition-press);
- animation: jiggle-subtle 0.3s ease-out forwards;
- }
- .btn:disabled {
- opacity: 0.6;
- cursor: not-allowed;
- box-shadow: var(--shadow-sm);
- }
- .btn-secondary { background-color: var(--secondary); }
- .btn-neutral { background-color: var(--light); color: var(--dark); }
- .btn-danger { background-color: var(--danger); color: var(--light); }
- .btn-sm { padding: 0.5rem 1rem; font-size: 0.9rem; }
- .btn-icon-only { padding: 0.6rem; }
- .btn-icon-only .icon { margin-right: 0; }
+.btn:focus-visible {
+ box-shadow: 0 0 0 var(--focus-outline-width) var(--focus-outline-color),
+ var(--shadow-lg);
+}
- @keyframes jiggle-subtle {
- 0%, 100% { transform: translate(2px, 2px) scale(0.98) rotate(0deg); }
- 25% { transform: translate(2px, 2px) scale(0.98) rotate(-0.5deg); }
- 75% { transform: translate(2px, 2px) scale(0.98) rotate(0.5deg); }
- }
+.form-input:focus-visible {
+ box-shadow: var(--shadow-inset),
+ 0 0 0 var(--focus-outline-width) var(--focus-outline-color),
+ var(--shadow-sm);
+}
- /* Cards */
- .card {
- background-color: var(--light);
- border: var(--border);
- padding: 1.5rem;
- box-shadow: var(--shadow-md);
- margin-bottom: 2rem;
- position: relative;
- /* overflow: hidden; */ /* REMOVED overflow: hidden which can clip tooltips */
- /* Add transition back if subtle hover is desired, but not transform */
- transition: box-shadow var(--transition-speed) var(--transition-ease-out);
- }
- /* Removed .card:hover transform/shadow increase */
- .card::before {
- content: "";
- position: absolute;
- inset: 0;
- background-image: var(--paper-texture);
- opacity: 0.6;
- z-index: 0;
- pointer-events: none; /* Prevent texture from interfering */
- }
- .card > * {
- position: relative;
- z-index: 1; /* Ensure content is above texture */
- }
- .card-header {
- margin: -1.5rem -1.5rem 1.5rem -1.5rem;
- padding: 1rem 1.5rem;
- border-bottom: var(--border);
- font-weight: bold;
- background-color: rgba(255, 255, 255, 0.5);
- }
- .card-body {
- margin-bottom: 1rem;
- }
- .card-footer {
- display: flex;
- justify-content: flex-end;
- align-items: center;
- margin: 1.5rem -1.5rem -1.5rem -1.5rem;
- padding: 1rem 1.5rem;
- border-top: var(--border);
- background-color: rgba(255, 255, 255, 0.5);
- }
- /* Empty State Card */
- .empty-state-card {
- text-align: center;
- padding: 3rem 1.5rem;
- }
- .empty-state-card .icon-lg {
- display: block;
- margin: 0 auto 1rem auto;
- width: 50px;
- height: 50px;
- opacity: 0.5;
- }
- .empty-state-card h3 { border: none; padding: 0; margin-bottom: 0.5rem; }
- .empty-state-card h3::after { display: none; }
- .empty-state-card p { margin-bottom: 1.5rem; opacity: 0.8; }
+.list-item:focus-visible {
+ /* Focus on list item might need adjustment if using swipe */
+ outline-offset: -var(--border-width);
+ z-index: 10;
+}
- /* Forms */
- .form-group { margin-bottom: 1.5rem; }
- .form-label {
- display: block;
- margin-bottom: 0.5rem;
- font-weight: bold;
- color: var(--dark);
- text-transform: uppercase;
- font-size: 0.9rem;
- letter-spacing: 0.5px;
- }
- .form-input,
- select.form-input,
- textarea.form-input {
- width: 100%;
- padding: 0.75rem;
- border: var(--border);
- background-color: var(--light);
- font-family: inherit;
- font-size: 1rem;
- box-shadow: var(--shadow-inset), var(--shadow-sm);
- transition: transform var(--transition-speed) var(--transition-ease-out),
- box-shadow var(--transition-speed) var(--transition-ease-out),
- border-color var(--transition-speed) var(--transition-ease-out);
- box-sizing: border-box;
- appearance: none;
- border-radius: 0;
- }
- textarea.form-input { line-height: 1.5; min-height: 80px; }
- select.form-input {
- background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='%23393e46'%3E%3Cpath d='M7 10l5 5 5-5H7z'/%3E%3C/svg%3E");
- background-repeat: no-repeat;
- background-position: right 0.75rem center;
- background-size: 1.5em;
- padding-right: 2.5rem;
- }
- .form-input:focus {
- outline: none; /* Use focus-visible */
- transform: translate(1px, 1px);
- border-color: var(--primary);
- }
- .form-input.error { border-color: var(--danger); background-color: #ffeeee; }
- .form-input:disabled { background-color: rgba(0, 0, 0, 0.05); opacity: 0.7; cursor: not-allowed; box-shadow: var(--shadow-inset); }
+.tab-item:focus-visible {
+ outline-offset: 4px;
+ z-index: 5;
+ /* Higher than non-focused tabs */
+}
- /* Checkbox & Radio */
- .checkbox-group, .radio-group { margin-bottom: 1rem; background: rgba(0,0,0,0.02); padding: 0.5rem; border: 1px solid rgba(0,0,0,0.1); }
- .checkbox-label, .radio-label { position: relative; padding-left: 2.8rem; margin-bottom: 0.75rem; cursor: pointer; display: flex; align-items: center; min-height: 30px; }
- .checkbox-label input, .radio-label input { position: absolute; opacity: 0; cursor: pointer; height: 100%; width: 100%; top: 0; left: 0; margin: 0; }
- .checkmark { position: absolute; top: 50%; transform: translateY(-50%); left: 0.5rem; height: 28px; width: 28px; background-color: var(--light); border: var(--border); box-shadow: var(--shadow-sm); transition: background-color var(--transition-speed) var(--transition-ease-out); pointer-events: none; }
- .radio-mark { border-radius: 50%; }
- .checkbox-label input:checked ~ .checkmark:after, .radio-label input:checked ~ .checkmark:after { content: ""; position: absolute; display: block; transform-origin: center center; }
- .checkbox-label .checkmark:after { left: 8px; top: 3px; width: 7px; height: 14px; border: solid var(--black); border-width: 0 4px 4px 0; transform: rotate(45deg) scale(0); animation: checkmark-appear var(--transition-speed) var(--transition-ease-out) forwards; }
- .radio-label .checkmark:after { top: 5px; left: 5px; width: 12px; height: 12px; background-color: var(--black); border-radius: 50%; transform: scale(0); animation: radio-appear var(--transition-speed) var(--transition-ease-out) forwards; }
- @keyframes checkmark-appear { 0% { transform: scale(0) rotate(45deg); opacity: 0; } 70% { transform: scale(1.1) rotate(45deg); opacity: 1; } 100% { transform: scale(1) rotate(45deg); opacity: 1; } }
- @keyframes radio-appear { 0% { transform: scale(0); opacity: 0; } 70% { transform: scale(1.1); opacity: 1; } 100% { transform: scale(1); opacity: 1; } }
+.checkbox-label input:focus-visible~.checkmark,
+.radio-label input:focus-visible~.checkmark {
+ outline: var(--focus-outline);
+ outline-offset: var(--focus-outline-offset);
+ box-shadow: var(--shadow-sm),
+ 0 0 0 var(--focus-outline-width) var(--focus-outline-color);
+}
- /* Lists */
- .item-list { list-style: none; padding: 0; margin: 0; }
- .list-item {
- border: var(--border);
- padding: 0; /* Remove padding here, add to content */
- margin-bottom: 1rem;
- background-color: var(--light);
- box-shadow: var(--shadow-md);
- display: flex; /* Use flex on the outer item */
- align-items: stretch; /* Stretch children vertically */
- transition: box-shadow var(--transition-speed) var(--transition-ease-out);
- position: relative;
- overflow: hidden; /* Needed for swipe actions reveal */
- }
- .list-item::before { content: ""; position: absolute; inset: 0; background-image: var(--paper-texture); opacity: 0.4; z-index: 0; pointer-events: none; }
- .list-item.completed .item-text { text-decoration: line-through; text-decoration-thickness: 2px; text-decoration-color: var(--dark); }
- .list-item.completed { opacity: 0.7; }
- /* --- Swipe Functionality Structure --- */
- .list-item-content {
- display: flex;
- flex-wrap: wrap; /* Allow wrapping inside content area */
- align-items: center;
- padding: 1rem; /* Add padding here */
- flex-grow: 1; /* Take available space */
- background-color: var(--light); /* Ensure bg covers area */
- position: relative; /* To stay above ::before */
- z-index: 1; /* Above texture */
- transition: transform 0.3s ease-out; /* Swipe animation */
- width: 100%; /* Ensure it takes full width initially */
- }
- .swipe-actions {
- position: absolute;
- top: 0;
- right: 0;
- height: 100%;
- display: flex;
- align-items: stretch; /* Make buttons fill height */
- z-index: 0; /* Below content initially */
- transform: translateX(100%); /* Initially hidden off-screen */
- transition: transform 0.3s ease-out;
- }
- .swipe-actions .btn {
- height: 100%;
- margin: 0;
- border-radius: 0;
- border-left: var(--border); /* Separator */
- border-top: none;
- border-bottom: none;
- border-right: none;
- box-shadow: none;
- font-size: 0.9rem;
- min-width: 80px; /* Ensure button has width */
- }
- /* State when swiped (JS adds/removes this class) */
- .list-item.is-swiped .list-item-content {
- /* Adjust translateX based on desired swipe distance/action width */
- transform: translateX(-160px); /* Example: width of two buttons */
- }
- .list-item.is-swiped .swipe-actions {
- transform: translateX(0); /* Reveal actions */
- }
- /* -------------------------------------- */
- /* Content layout inside .list-item-content */
- .list-item-main { /* Wrapper for checkbox and text */
- display: flex;
- align-items: center;
- flex-grow: 1; /* Takes up space, pushing details right */
- margin-right: 1rem; /* Space before details */
- min-width: 150px; /* Prevent excessive shrinking */
- }
- .list-item .checkbox-label { flex-shrink: 0; margin-bottom: 0; }
- .item-text { margin-left: 1rem; flex-grow: 1; min-width: 50px; } /* Allow text to grow */
- .list-item-details { /* Wrapper for avatar, badges, actions (non-swipe) */
- display: flex;
- align-items: center;
- flex-wrap: nowrap; /* Prevent wrapping of these items */
- flex-shrink: 0; /* Don't shrink this container */
- margin-left: auto; /* Push to the right on larger screens */
- }
- .list-item-details > * { margin-left: 0.5rem; } /* Spacing between items in details */
- .list-item-details > :first-child { margin-left: 0; }
- .list-item-details .avatar { margin: 0; } /* Reset avatar margin */
- .list-item-actions { /* Non-swipe actions styling */
- display: flex;
- align-items: center;
- padding-left: 0.5rem; /* Space before non-swipe actions */
- }
- .list-item-actions .btn { padding: 0.4rem 0.8rem; font-size: 0.9rem; margin: 0 0 0 0.25rem; }
+.switch-container input:focus-visible+.switch {
+ outline: var(--focus-outline);
+ outline-offset: var(--focus-outline-offset);
+}
- /* Badges & Avatars */
- .item-badge { display: inline-block; padding: 0.25rem 0.6rem; background-color: var(--secondary); border: 2px solid var(--black); margin: 0.25rem 0; font-weight: bold; box-shadow: var(--shadow-sm); font-size: 0.85rem; text-transform: uppercase; flex-shrink: 0; position: relative; }
- .badge-accent { background-color: var(--accent); }
- .badge-accent.badge-sticky::after { content: ""; position: absolute; bottom: -1px; right: -1px; width: 50%; height: 50%; background: linear-gradient( 135deg, transparent 50%, rgba(0,0,0,0.15) 50% ); transform: skew(-15deg, -15deg) translate(2px, 2px); filter: blur(1px); border-bottom-right-radius: 3px; z-index: -1; box-shadow: 2px 2px 3px rgba(0,0,0,0.2); }
- .badge-settled { background-color: var(--secondary-accent); color: var(--dark); }
- .badge-pending { background-color: var(--warning); color: var(--dark); }
- .avatar { display: inline-flex; align-items: center; justify-content: center; width: 36px; height: 36px; border-radius: 50%; background-color: var(--secondary); color: var(--dark); border: 2px solid var(--black); box-shadow: var(--shadow-sm); font-weight: bold; font-size: 1rem; text-transform: uppercase; margin: 0.25rem; flex-shrink: 0; overflow: hidden; cursor: default; }
- .avatar img { width: 100%; height: 100%; object-fit: cover; }
+.avatar:focus-visible {
+ box-shadow: 0 0 0 var(--focus-outline-width) var(--focus-outline-color),
+ var(--shadow-sm);
+}
- /* Tabs */
- .tabs { margin-bottom: 2rem; }
- .tab-list { display: flex; flex-wrap: wrap; list-style: none; padding: 0; margin: 0 0 -3px 0; /* Overlap border */ position: relative; z-index: 1; /* Above content by default */ }
- .tab-item { padding: 0.75rem 1.5rem; background-color: var(--light); border: var(--border); border-bottom-color: var(--border-color); margin-right: 0.5rem; margin-bottom: 0; /* Remove bottom margin */ cursor: pointer; font-weight: bold; position: relative; box-shadow: var(--shadow-sm); transition: transform var(--transition-speed) var(--transition-ease-out), box-shadow var(--transition-speed) var(--transition-ease-out), background-color var(--transition-speed) var(--transition-ease-out), color var(--transition-speed) var(--transition-ease-out), border-color var(--transition-speed) var(--transition-ease-out); text-transform: uppercase; letter-spacing: 0.5px; flex-grow: 0; }
- .tab-item[aria-selected="true"] {
- background-color: var(--primary);
- color: var(--dark);
- border-color: var(--black); /* Ensure all borders are black */
- border-bottom-color: var(--primary); /* Match background to hide border */
- box-shadow: var(--shadow-md);
- z-index: 2; /* Bring active tab forward */
- /* transform: translateY(-3px); REMOVED */
- }
- .tab-item:not([aria-selected="true"]):hover { background-color: var(--secondary); transform: translateY(-2px); box-shadow: var(--shadow-md); }
- .tab-content {
- padding: 1.5rem;
- border: var(--border);
- background-color: var(--light);
- box-shadow: var(--shadow-md);
- position: relative;
- overflow: hidden; /* Keep hidden for content flow */
- margin-top: -3px; /* Pull up behind active tab */
- z-index: 0; /* Ensure content is behind tab list */
- }
- .tab-content[hidden] { display: none; }
- .tab-content::before { content: ""; position: absolute; inset: 0; background-image: var(--paper-texture); opacity: 0.6; z-index: 0; pointer-events: none; }
- .tab-content > * { position: relative; z-index: 1; }
+.tooltip .tooltip-trigger:focus-visible {
+ outline: var(--focus-outline);
+ outline-offset: var(--focus-outline-offset);
+}
- /* Modal */
- .modal-backdrop { position: fixed; inset: 0; background-color: rgba(57, 62, 70, 0.7); display: flex; align-items: center; justify-content: center; z-index: 1000; opacity: 0; visibility: hidden; transition: opacity var(--transition-speed) var(--transition-ease-out), visibility 0s linear var(--transition-speed); }
- .modal-backdrop.open { opacity: 1; visibility: visible; transition: opacity var(--transition-speed) var(--transition-ease-out), visibility 0s linear 0s; }
- .modal-container { background-color: var(--light); border: var(--border); width: 90%; max-width: 550px; box-shadow: var(--shadow-lg); position: relative; /* overflow: hidden; */ /* Can cause tooltip clipping */ transform: scale(0.95) translateY(-20px); transition: transform var(--transition-speed) var(--transition-ease-out); max-height: 90vh; display: flex; flex-direction: column; }
- .modal-container::before { content: ""; position: absolute; inset: 0; background-image: var(--paper-texture); opacity: 0.6; z-index: 0; pointer-events: none; }
- .modal-backdrop.open .modal-container { transform: scale(1) translateY(0); }
- .modal-header { padding: 1rem 1.5rem; border-bottom: var(--border); display: flex; justify-content: space-between; align-items: center; background-color: rgba(255, 255, 255, 0.5); flex-shrink: 0; position: relative; z-index: 1; }
- .modal-header h3 { margin-bottom: 0; padding-bottom: 0; }
- .modal-header h3::after { display: none; }
- .modal-body { padding: 1.5rem; overflow-y: auto; position: relative; z-index: 1; flex-grow: 1; }
- .modal-footer { padding: 1rem 1.5rem; border-top: var(--border); display: flex; justify-content: flex-end; background-color: rgba(255, 255, 255, 0.5); flex-shrink: 0; position: relative; z-index: 1; }
- .close-button { background: none; border: none; font-size: 2rem; font-weight: bold; cursor: pointer; padding: 0; line-height: 1; color: var(--dark); transition: color var(--transition-speed) var(--transition-ease-out), transform var(--transition-speed-fast) ease-out; }
- .close-button .icon { margin: 0; }
- .close-button:hover { color: var(--danger); transform: scale(1.1); }
- .modal-container.confirm-modal .modal-body { text-align: center; }
- .modal-container.confirm-modal .modal-footer { justify-content: center; }
- .modal-container.confirm-modal .icon-lg { color: var(--danger); margin-bottom: 1rem; display: inline-block; }
+/* Headings */
+h1,
+h2,
+h3 {
+ font-weight: bold;
+ color: var(--dark);
+ text-transform: uppercase;
+ letter-spacing: 1.5px;
+ position: relative;
+ display: inline-block;
+ margin-bottom: 1.5rem;
+ padding-bottom: 8px;
+}
- /* Alerts */
- .alert {
- padding: 1rem 1.5rem;
- margin-bottom: 1.5rem;
- border: var(--border);
- border-left-width: 6px; /* Thicker left border */
- box-shadow: var(--shadow-md);
- font-weight: bold;
- position: relative;
- overflow: hidden; /* Keep overflow for ::before */
- letter-spacing: 0.5px;
- display: flex;
- align-items: center;
- justify-content: space-between; /* Space out content and close button */
- }
- .alert::before { content: ""; position: absolute; inset: 0; background-image: var(--paper-texture); opacity: 0.6; z-index: 0; pointer-events: none;}
- .alert > .alert-content { /* Wrap main content */
- display: flex;
- align-items: center;
- flex-grow: 1; /* Take available space */
- margin-right: 1rem; /* Space before close button */
- position: relative; z-index: 1;
- }
- .alert .icon { margin-right: 0.8em; flex-shrink: 0; }
- .alert-close-btn {
- background: none;
- border: none;
- color: inherit; /* Inherit color from alert text */
- opacity: 0.7;
- font-size: 1.5rem;
- line-height: 1;
- padding: 0 0.25rem;
- cursor: pointer;
- transition: opacity 0.2s ease-out;
- flex-shrink: 0; /* Prevent shrinking */
- position: relative; z-index: 1;
- }
- .alert-close-btn:hover { opacity: 1; }
- .alert-close-btn .icon { margin: 0; }
+h1::after,
+h2::after,
+h3::after {
+ content: "";
+ position: absolute;
+ bottom: 0;
+ left: 0;
+ width: 100%;
+ height: var(--border-width);
+ background-color: var(--primary);
+ box-shadow: var(--shadow-sm);
+}
- .alert-success { background-color: var(--success); color: var(--dark); border-left-color: hsl(120, 60%, 45%); } /* Darker green border */
- .alert-warning { background-color: var(--warning); color: var(--dark); border-left-color: hsl(45, 100%, 45%); } /* Darker yellow/orange border */
- .alert-error { background-color: #ffcccc; border-color: var(--danger); color: var(--dark); border-left-color: var(--danger); }
- .alert-info { background-color: var(--secondary-accent); color: var(--dark); border-left-color: hsl(200, 100%, 45%); } /* Darker blue border */
+h1 {
+ font-size: clamp(2rem, 5vw, 2.5rem);
+}
+
+h2 {
+ font-size: clamp(1.6rem, 4vw, 2rem);
+}
+
+h3 {
+ font-size: clamp(1.3rem, 3.5vw, 1.5rem);
+}
+
+/* Icon Base Style */
+.icon {
+ display: inline-block;
+ width: 1.1em;
+ height: 1.1em;
+ vertical-align: -0.15em;
+ margin-right: 0.4em;
+ fill: currentColor;
+}
+
+.btn .icon {
+ margin-right: 0.5em;
+}
+
+button>.icon:last-child {
+ margin-right: 0;
+}
+
+.icon-sm {
+ width: 0.9em;
+ height: 0.9em;
+}
+
+.icon-lg {
+ width: 1.5em;
+ height: 1.5em;
+}
+
+/* Buttons */
+.btn {
+ background-color: var(--primary);
+ color: var(--dark);
+ border: var(--border);
+ font-family: inherit;
+ font-size: 1rem;
+ font-weight: bold;
+ padding: 0.8rem 1.6rem;
+ cursor: pointer;
+ box-shadow: var(--shadow-md);
+ transition: transform var(--transition-speed) var(--transition-ease-out),
+ box-shadow var(--transition-speed) var(--transition-ease-out),
+ background-color var(--transition-speed) var(--transition-ease-out);
+ position: relative;
+ text-transform: uppercase;
+ letter-spacing: 1px;
+ margin: 0.5rem;
+ display: inline-flex;
+ align-items: center;
+ justify-content: center;
+ text-decoration: none;
+ text-align: center;
+ touch-action: manipulation;
+ overflow: hidden;
+}
+
+.btn:hover:not(:disabled) {
+ transform: translate(-3px, -3px);
+ box-shadow: var(--shadow-lg);
+}
+
+.btn:active:not(:disabled) {
+ transform: translate(2px, 2px) scale(0.98);
+ box-shadow: var(--shadow-sm);
+ transition-duration: var(--transition-speed-fast);
+ transition-timing-function: var(--transition-press);
+ animation: jiggle-subtle 0.3s ease-out forwards;
+}
+
+.btn:disabled {
+ opacity: 0.6;
+ cursor: not-allowed;
+ box-shadow: var(--shadow-sm);
+}
+
+.btn-secondary {
+ background-color: var(--secondary);
+}
+
+.btn-neutral {
+ background-color: var(--light);
+ color: var(--dark);
+}
+
+.btn-danger {
+ background-color: var(--danger);
+ color: var(--light);
+}
+
+.btn-sm {
+ padding: 0.5rem 1rem;
+ font-size: 0.9rem;
+}
+
+.btn-icon-only {
+ padding: 0.6rem;
+}
+
+.btn-icon-only .icon {
+ margin-right: 0;
+}
+
+@keyframes jiggle-subtle {
+
+ 0%,
+ 100% {
+ transform: translate(2px, 2px) scale(0.98) rotate(0deg);
+ }
+
+ 25% {
+ transform: translate(2px, 2px) scale(0.98) rotate(-0.5deg);
+ }
+
+ 75% {
+ transform: translate(2px, 2px) scale(0.98) rotate(0.5deg);
+ }
+}
+
+/* Cards */
+.card {
+ background-color: var(--light);
+ border: var(--border);
+ padding: 1.5rem;
+ box-shadow: var(--shadow-md);
+ margin-bottom: 2rem;
+ position: relative;
+ /* overflow: hidden; */
+ /* REMOVED overflow: hidden which can clip tooltips */
+ /* Add transition back if subtle hover is desired, but not transform */
+ transition: box-shadow var(--transition-speed) var(--transition-ease-out);
+}
+
+/* Removed .card:hover transform/shadow increase */
+.card::before {
+ content: "";
+ position: absolute;
+ inset: 0;
+ background-image: var(--paper-texture);
+ opacity: 0.6;
+ z-index: 0;
+ pointer-events: none;
+ /* Prevent texture from interfering */
+}
+
+.card>* {
+ position: relative;
+ z-index: 1;
+ /* Ensure content is above texture */
+}
+
+.card-header {
+ margin: -1.5rem -1.5rem 1.5rem -1.5rem;
+ padding: 1rem 1.5rem;
+ border-bottom: var(--border);
+ font-weight: bold;
+ background-color: rgba(255, 255, 255, 0.5);
+}
+
+.card-body {
+ margin-bottom: 1rem;
+}
+
+.card-footer {
+ display: flex;
+ justify-content: flex-end;
+ align-items: center;
+ margin: 1.5rem -1.5rem -1.5rem -1.5rem;
+ padding: 1rem 1.5rem;
+ border-top: var(--border);
+ background-color: rgba(255, 255, 255, 0.5);
+}
+
+/* Empty State Card */
+.empty-state-card {
+ text-align: center;
+ padding: 3rem 1.5rem;
+}
+
+.empty-state-card .icon-lg {
+ display: block;
+ margin: 0 auto 1rem auto;
+ width: 50px;
+ height: 50px;
+ opacity: 0.5;
+}
+
+.empty-state-card h3 {
+ border: none;
+ padding: 0;
+ margin-bottom: 0.5rem;
+}
+
+.empty-state-card h3::after {
+ display: none;
+}
+
+.empty-state-card p {
+ margin-bottom: 1.5rem;
+ opacity: 0.8;
+}
+
+/* Forms */
+.form-group {
+ margin-bottom: 1.5rem;
+}
+
+.form-label {
+ display: block;
+ margin-bottom: 0.5rem;
+ font-weight: bold;
+ color: var(--dark);
+ text-transform: uppercase;
+ font-size: 0.9rem;
+ letter-spacing: 0.5px;
+}
+
+.form-input,
+select.form-input,
+textarea.form-input {
+ width: 100%;
+ padding: 0.75rem;
+ border: var(--border);
+ background-color: var(--light);
+ font-family: inherit;
+ font-size: 1rem;
+ box-shadow: var(--shadow-inset), var(--shadow-sm);
+ transition: transform var(--transition-speed) var(--transition-ease-out),
+ box-shadow var(--transition-speed) var(--transition-ease-out),
+ border-color var(--transition-speed) var(--transition-ease-out);
+ box-sizing: border-box;
+ appearance: none;
+ border-radius: 0;
+}
+
+textarea.form-input {
+ line-height: 1.5;
+ min-height: 80px;
+}
+
+select.form-input {
+ background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='%23393e46'%3E%3Cpath d='M7 10l5 5 5-5H7z'/%3E%3C/svg%3E");
+ background-repeat: no-repeat;
+ background-position: right 0.75rem center;
+ background-size: 1.5em;
+ padding-right: 2.5rem;
+}
+
+.form-input:focus {
+ outline: none;
+ /* Use focus-visible */
+ transform: translate(1px, 1px);
+ border-color: var(--primary);
+}
+
+.form-input.error {
+ border-color: var(--danger);
+ background-color: #ffeeee;
+}
+
+.form-input:disabled {
+ background-color: rgba(0, 0, 0, 0.05);
+ opacity: 0.7;
+ cursor: not-allowed;
+ box-shadow: var(--shadow-inset);
+}
+
+/* Checkbox & Radio */
+.checkbox-group,
+.radio-group {
+ margin-bottom: 1rem;
+ background: rgba(0, 0, 0, 0.02);
+ padding: 0.5rem;
+ border: 1px solid rgba(0, 0, 0, 0.1);
+}
+
+.checkbox-label,
+.radio-label {
+ position: relative;
+ padding-left: 2.8rem;
+ margin-bottom: 0.75rem;
+ cursor: pointer;
+ display: flex;
+ align-items: center;
+ min-height: 30px;
+}
+
+.checkbox-label input,
+.radio-label input {
+ position: absolute;
+ opacity: 0;
+ cursor: pointer;
+ height: 100%;
+ width: 100%;
+ top: 0;
+ left: 0;
+ margin: 0;
+}
+
+.checkmark {
+ position: absolute;
+ top: 50%;
+ transform: translateY(-50%);
+ left: 0.5rem;
+ height: 28px;
+ width: 28px;
+ background-color: var(--light);
+ border: var(--border);
+ box-shadow: var(--shadow-sm);
+ transition: background-color var(--transition-speed) var(--transition-ease-out);
+ pointer-events: none;
+}
+
+.radio-mark {
+ border-radius: 50%;
+}
+
+.checkbox-label input:checked~.checkmark:after,
+.radio-label input:checked~.checkmark:after {
+ content: "";
+ position: absolute;
+ display: block;
+ transform-origin: center center;
+}
+
+.checkbox-label .checkmark:after {
+ left: 8px;
+ top: 3px;
+ width: 7px;
+ height: 14px;
+ border: solid var(--black);
+ border-width: 0 4px 4px 0;
+ transform: rotate(45deg) scale(0);
+ animation: checkmark-appear var(--transition-speed) var(--transition-ease-out) forwards;
+}
+
+.radio-label .checkmark:after {
+ top: 5px;
+ left: 5px;
+ width: 12px;
+ height: 12px;
+ background-color: var(--black);
+ border-radius: 50%;
+ transform: scale(0);
+ animation: radio-appear var(--transition-speed) var(--transition-ease-out) forwards;
+}
+
+@keyframes checkmark-appear {
+ 0% {
+ transform: scale(0) rotate(45deg);
+ opacity: 0;
+ }
+
+ 70% {
+ transform: scale(1.1) rotate(45deg);
+ opacity: 1;
+ }
+
+ 100% {
+ transform: scale(1) rotate(45deg);
+ opacity: 1;
+ }
+}
+
+@keyframes radio-appear {
+ 0% {
+ transform: scale(0);
+ opacity: 0;
+ }
+
+ 70% {
+ transform: scale(1.1);
+ opacity: 1;
+ }
+
+ 100% {
+ transform: scale(1);
+ opacity: 1;
+ }
+}
+
+/* Lists */
+.item-list {
+ list-style: none;
+ padding: 0;
+ margin: 0;
+}
+
+.list-item {
+ border: var(--border);
+ padding: 0;
+ /* Remove padding here, add to content */
+ margin-bottom: 1rem;
+ background-color: var(--light);
+ box-shadow: var(--shadow-md);
+ display: flex;
+ /* Use flex on the outer item */
+ align-items: stretch;
+ /* Stretch children vertically */
+ transition: box-shadow var(--transition-speed) var(--transition-ease-out);
+ position: relative;
+ overflow: hidden;
+ /* Needed for swipe actions reveal */
+}
+
+.list-item::before {
+ content: "";
+ position: absolute;
+ inset: 0;
+ background-image: var(--paper-texture);
+ opacity: 0.4;
+ z-index: 0;
+ pointer-events: none;
+}
+
+.list-item.completed .item-text {
+ text-decoration: line-through;
+ text-decoration-thickness: 2px;
+ text-decoration-color: var(--dark);
+}
+
+.list-item.completed {
+ opacity: 0.7;
+}
+
+/* --- Swipe Functionality Structure --- */
+.list-item-content {
+ display: flex;
+ flex-wrap: wrap;
+ /* Allow wrapping inside content area */
+ align-items: center;
+ padding: 1rem;
+ /* Add padding here */
+ flex-grow: 1;
+ /* Take available space */
+ background-color: var(--light);
+ /* Ensure bg covers area */
+ position: relative;
+ /* To stay above ::before */
+ z-index: 1;
+ /* Above texture */
+ transition: transform 0.3s ease-out;
+ /* Swipe animation */
+ width: 100%;
+ /* Ensure it takes full width initially */
+}
+
+.swipe-actions {
+ position: absolute;
+ top: 0;
+ right: 0;
+ height: 100%;
+ display: flex;
+ align-items: stretch;
+ /* Make buttons fill height */
+ z-index: 0;
+ /* Below content initially */
+ transform: translateX(100%);
+ /* Initially hidden off-screen */
+ transition: transform 0.3s ease-out;
+}
+
+.swipe-actions .btn {
+ height: 100%;
+ margin: 0;
+ border-radius: 0;
+ border-left: var(--border);
+ /* Separator */
+ border-top: none;
+ border-bottom: none;
+ border-right: none;
+ box-shadow: none;
+ font-size: 0.9rem;
+ min-width: 80px;
+ /* Ensure button has width */
+}
+
+/* State when swiped (JS adds/removes this class) */
+.list-item.is-swiped .list-item-content {
+ /* Adjust translateX based on desired swipe distance/action width */
+ transform: translateX(-160px);
+ /* Example: width of two buttons */
+}
+
+.list-item.is-swiped .swipe-actions {
+ transform: translateX(0);
+ /* Reveal actions */
+}
+
+/* -------------------------------------- */
+/* Content layout inside .list-item-content */
+.list-item-main {
+ /* Wrapper for checkbox and text */
+ display: flex;
+ align-items: center;
+ flex-grow: 1;
+ /* Takes up space, pushing details right */
+ margin-right: 1rem;
+ /* Space before details */
+ min-width: 150px;
+ /* Prevent excessive shrinking */
+}
+
+.list-item .checkbox-label {
+ flex-shrink: 0;
+ margin-bottom: 0;
+}
+
+.item-text {
+ margin-left: 1rem;
+ flex-grow: 1;
+ min-width: 50px;
+}
+
+/* Allow text to grow */
+.list-item-details {
+ /* Wrapper for avatar, badges, actions (non-swipe) */
+ display: flex;
+ align-items: center;
+ flex-wrap: nowrap;
+ /* Prevent wrapping of these items */
+ flex-shrink: 0;
+ /* Don't shrink this container */
+ margin-left: auto;
+ /* Push to the right on larger screens */
+}
+
+.list-item-details>* {
+ margin-left: 0.5rem;
+}
+
+/* Spacing between items in details */
+.list-item-details> :first-child {
+ margin-left: 0;
+}
+
+.list-item-details .avatar {
+ margin: 0;
+}
+
+/* Reset avatar margin */
+.list-item-actions {
+ /* Non-swipe actions styling */
+ display: flex;
+ align-items: center;
+ padding-left: 0.5rem;
+ /* Space before non-swipe actions */
+}
+
+.list-item-actions .btn {
+ padding: 0.4rem 0.8rem;
+ font-size: 0.9rem;
+ margin: 0 0 0 0.25rem;
+}
+
+/* Badges & Avatars */
+.item-badge {
+ display: inline-block;
+ padding: 0.25rem 0.6rem;
+ background-color: var(--secondary);
+ border: 2px solid var(--black);
+ margin: 0.25rem 0;
+ font-weight: bold;
+ box-shadow: var(--shadow-sm);
+ font-size: 0.85rem;
+ text-transform: uppercase;
+ flex-shrink: 0;
+ position: relative;
+}
+
+.badge-accent {
+ background-color: var(--accent);
+}
+
+.badge-accent.badge-sticky::after {
+ content: "";
+ position: absolute;
+ bottom: -1px;
+ right: -1px;
+ width: 50%;
+ height: 50%;
+ background: linear-gradient(135deg, transparent 50%, rgba(0, 0, 0, 0.15) 50%);
+ transform: skew(-15deg, -15deg) translate(2px, 2px);
+ filter: blur(1px);
+ border-bottom-right-radius: 3px;
+ z-index: -1;
+ box-shadow: 2px 2px 3px rgba(0, 0, 0, 0.2);
+}
+
+.badge-settled {
+ background-color: var(--secondary-accent);
+ color: var(--dark);
+}
+
+.badge-pending {
+ background-color: var(--warning);
+ color: var(--dark);
+}
+
+.avatar {
+ display: inline-flex;
+ align-items: center;
+ justify-content: center;
+ width: 36px;
+ height: 36px;
+ border-radius: 50%;
+ background-color: var(--secondary);
+ color: var(--dark);
+ border: 2px solid var(--black);
+ box-shadow: var(--shadow-sm);
+ font-weight: bold;
+ font-size: 1rem;
+ text-transform: uppercase;
+ margin: 0.25rem;
+ flex-shrink: 0;
+ overflow: hidden;
+ cursor: default;
+}
+
+.avatar img {
+ width: 100%;
+ height: 100%;
+ object-fit: cover;
+}
+
+/* Tabs */
+.tabs {
+ margin-bottom: 2rem;
+}
+
+.tab-list {
+ display: flex;
+ flex-wrap: wrap;
+ list-style: none;
+ padding: 0;
+ margin: 0 0 -3px 0;
+ /* Overlap border */
+ position: relative;
+ z-index: 1;
+ /* Above content by default */
+}
+
+.tab-item {
+ padding: 0.75rem 1.5rem;
+ background-color: var(--light);
+ border: var(--border);
+ border-bottom-color: var(--border-color);
+ margin-right: 0.5rem;
+ margin-bottom: 0;
+ /* Remove bottom margin */
+ cursor: pointer;
+ font-weight: bold;
+ position: relative;
+ box-shadow: var(--shadow-sm);
+ transition: transform var(--transition-speed) var(--transition-ease-out), box-shadow var(--transition-speed) var(--transition-ease-out), background-color var(--transition-speed) var(--transition-ease-out), color var(--transition-speed) var(--transition-ease-out), border-color var(--transition-speed) var(--transition-ease-out);
+ text-transform: uppercase;
+ letter-spacing: 0.5px;
+ flex-grow: 0;
+}
+
+.tab-item[aria-selected="true"] {
+ background-color: var(--primary);
+ color: var(--dark);
+ border-color: var(--black);
+ /* Ensure all borders are black */
+ border-bottom-color: var(--primary);
+ /* Match background to hide border */
+ box-shadow: var(--shadow-md);
+ z-index: 2;
+ /* Bring active tab forward */
+ /* transform: translateY(-3px); REMOVED */
+}
+
+.tab-item:not([aria-selected="true"]):hover {
+ background-color: var(--secondary);
+ transform: translateY(-2px);
+ box-shadow: var(--shadow-md);
+}
+
+.tab-content {
+ padding: 1.5rem;
+ border: var(--border);
+ background-color: var(--light);
+ box-shadow: var(--shadow-md);
+ position: relative;
+ overflow: hidden;
+ /* Keep hidden for content flow */
+ margin-top: -3px;
+ /* Pull up behind active tab */
+ z-index: 0;
+ /* Ensure content is behind tab list */
+}
+
+.tab-content[hidden] {
+ display: none;
+}
+
+.tab-content::before {
+ content: "";
+ position: absolute;
+ inset: 0;
+ background-image: var(--paper-texture);
+ opacity: 0.6;
+ z-index: 0;
+ pointer-events: none;
+}
+
+.tab-content>* {
+ position: relative;
+ z-index: 1;
+}
+
+/* Modal */
+.modal-backdrop {
+ position: fixed;
+ inset: 0;
+ background-color: rgba(57, 62, 70, 0.7);
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ z-index: 1000;
+ opacity: 0;
+ visibility: hidden;
+ transition: opacity var(--transition-speed) var(--transition-ease-out), visibility 0s linear var(--transition-speed);
+}
+
+.modal-backdrop.open {
+ opacity: 1;
+ visibility: visible;
+ transition: opacity var(--transition-speed) var(--transition-ease-out), visibility 0s linear 0s;
+}
+
+.modal-container {
+ background-color: var(--light);
+ border: var(--border);
+ width: 90%;
+ max-width: 550px;
+ box-shadow: var(--shadow-lg);
+ position: relative;
+ /* overflow: hidden; */
+ /* Can cause tooltip clipping */
+ transform: scale(0.95) translateY(-20px);
+ transition: transform var(--transition-speed) var(--transition-ease-out);
+ max-height: 90vh;
+ display: flex;
+ flex-direction: column;
+}
+
+.modal-container::before {
+ content: "";
+ position: absolute;
+ inset: 0;
+ background-image: var(--paper-texture);
+ opacity: 0.6;
+ z-index: 0;
+ pointer-events: none;
+}
+
+.modal-backdrop.open .modal-container {
+ transform: scale(1) translateY(0);
+}
+
+.modal-header {
+ padding: 1rem 1.5rem;
+ border-bottom: var(--border);
+ display: flex;
+ justify-content: space-between;
+ align-items: center;
+ background-color: rgba(255, 255, 255, 0.5);
+ flex-shrink: 0;
+ position: relative;
+ z-index: 1;
+}
+
+.modal-header h3 {
+ margin-bottom: 0;
+ padding-bottom: 0;
+}
+
+.modal-header h3::after {
+ display: none;
+}
+
+.modal-body {
+ padding: 1.5rem;
+ overflow-y: auto;
+ position: relative;
+ z-index: 1;
+ flex-grow: 1;
+}
+
+.modal-footer {
+ padding: 1rem 1.5rem;
+ border-top: var(--border);
+ display: flex;
+ justify-content: flex-end;
+ background-color: rgba(255, 255, 255, 0.5);
+ flex-shrink: 0;
+ position: relative;
+ z-index: 1;
+}
+
+.close-button {
+ background: none;
+ border: none;
+ font-size: 2rem;
+ font-weight: bold;
+ cursor: pointer;
+ padding: 0;
+ line-height: 1;
+ color: var(--dark);
+ transition: color var(--transition-speed) var(--transition-ease-out), transform var(--transition-speed-fast) ease-out;
+}
+
+.close-button .icon {
+ margin: 0;
+}
+
+.close-button:hover {
+ color: var(--danger);
+ transform: scale(1.1);
+}
+
+.modal-container.confirm-modal .modal-body {
+ text-align: center;
+}
+
+.modal-container.confirm-modal .modal-footer {
+ justify-content: center;
+}
+
+.modal-container.confirm-modal .icon-lg {
+ color: var(--danger);
+ margin-bottom: 1rem;
+ display: inline-block;
+}
+
+/* Alerts */
+.alert {
+ padding: 1rem 1.5rem;
+ margin-bottom: 1.5rem;
+ border: var(--border);
+ border-left-width: 6px;
+ /* Thicker left border */
+ box-shadow: var(--shadow-md);
+ font-weight: bold;
+ position: relative;
+ overflow: hidden;
+ /* Keep overflow for ::before */
+ letter-spacing: 0.5px;
+ display: flex;
+ align-items: center;
+ justify-content: space-between;
+ /* Space out content and close button */
+}
+
+.alert::before {
+ content: "";
+ position: absolute;
+ inset: 0;
+ background-image: var(--paper-texture);
+ opacity: 0.6;
+ z-index: 0;
+ pointer-events: none;
+}
+
+.alert>.alert-content {
+ /* Wrap main content */
+ display: flex;
+ align-items: center;
+ flex-grow: 1;
+ /* Take available space */
+ margin-right: 1rem;
+ /* Space before close button */
+ position: relative;
+ z-index: 1;
+}
+
+.alert .icon {
+ margin-right: 0.8em;
+ flex-shrink: 0;
+}
+
+.alert-close-btn {
+ background: none;
+ border: none;
+ color: inherit;
+ /* Inherit color from alert text */
+ opacity: 0.7;
+ font-size: 1.5rem;
+ line-height: 1;
+ padding: 0 0.25rem;
+ cursor: pointer;
+ transition: opacity 0.2s ease-out;
+ flex-shrink: 0;
+ /* Prevent shrinking */
+ position: relative;
+ z-index: 1;
+}
+
+.alert-close-btn:hover {
+ opacity: 1;
+}
+
+.alert-close-btn .icon {
+ margin: 0;
+}
+
+.alert-success {
+ background-color: var(--success);
+ color: var(--dark);
+ border-left-color: hsl(120, 60%, 45%);
+}
+
+/* Darker green border */
+.alert-warning {
+ background-color: var(--warning);
+ color: var(--dark);
+ border-left-color: hsl(45, 100%, 45%);
+}
+
+/* Darker yellow/orange border */
+.alert-error {
+ background-color: #ffcccc;
+ border-color: var(--danger);
+ color: var(--dark);
+ border-left-color: var(--danger);
+}
+
+.alert-info {
+ background-color: var(--secondary-accent);
+ color: var(--dark);
+ border-left-color: hsl(200, 100%, 45%);
+}
+
+/* Darker blue border */
- /* Progress Bar */
- .progress-container { width: 100%; height: 35px; background-color: var(--light); border: var(--border); box-shadow: var(--shadow-md); margin-bottom: 1.5rem; position: relative; overflow: hidden; }
- .progress-bar { height: 100%; background-color: var(--primary); position: relative; transition: width 0.5s var(--transition-ease-out); background-image: var(--progress-texture); display: flex; align-items: center; justify-content: center; }
- .progress-text { position: absolute; inset: 0; display: flex; align-items: center; justify-content: center; color: var(--dark); font-weight: bold; z-index: 1; text-shadow: 1px 1px 0px rgba(255, 255, 255, 0.7); font-size: 0.9rem; white-space: nowrap; }
+/* Progress Bar */
+.progress-container {
+ width: 100%;
+ height: 35px;
+ background-color: var(--light);
+ border: var(--border);
+ box-shadow: var(--shadow-md);
+ margin-bottom: 1.5rem;
+ position: relative;
+ overflow: hidden;
+}
- /* Toggle Switch - Refined */
- .switch-container {
- position: relative;
- display: inline-block;
- width: 64px; /* Slightly smaller */
- height: 34px; /* Slightly smaller */
- margin-bottom: 1rem;
- vertical-align: middle;
- }
- .switch-container input { position: absolute; opacity: 0; width: 100%; height: 100%; top: 0; left: 0; margin: 0; cursor: pointer; z-index: 2; }
- .switch {
- position: absolute;
- cursor: pointer;
- inset: 0;
- background-color: var(--light);
- border: var(--border);
- /* box-shadow: var(--shadow-inset), var(--shadow-sm); REMOVED - potential conflict */
- box-shadow: var(--shadow-inset); /* Keep inset shadow only */
- transition: background-color 0.4s var(--transition-ease-out);
- pointer-events: none;
- z-index: 1;
- }
- .switch:before {
- position: absolute;
- content: "";
- height: 24px; /* Adjusted size */
- width: 24px; /* Adjusted size */
- left: 2px; /* Adjusted position */
- top: 50%; /* Center vertically */
- background-color: var(--dark);
- border: 2px solid var(--light);
- box-shadow: var(--shadow-sm);
- transition: transform 0.4s var(--transition-ease-out),
- background-color 0.4s var(--transition-ease-out),
- border-color 0.4s var(--transition-ease-out);
- transform: translateY(-50%); /* Vertical centering */
- }
- .switch-container input:checked + .switch { background-color: var(--secondary-accent); }
- .switch-container input:checked + .switch:before {
- background-color: var(--light);
- border-color: var(--dark);
- /* Width (64) - border*2 (6) - left (2) - width (24) = 32 */
- transform: translate(30px, -50%); /* Adjusted translation */
- }
+.progress-bar {
+ height: 100%;
+ background-color: var(--primary);
+ position: relative;
+ transition: width 0.5s var(--transition-ease-out);
+ background-image: var(--progress-texture);
+ display: flex;
+ align-items: center;
+ justify-content: center;
+}
- /* Tables */
- .table-container { overflow-x: auto; margin-bottom: 1.5rem; border: var(--border); box-shadow: var(--shadow-md); background-color: var(--light); position: relative; /* overflow: hidden; */ /* Can clip tooltips */ }
- .table-container::before { content: ""; position: absolute; inset: 0; background-image: var(--paper-texture); opacity: 0.6; z-index: 0; pointer-events: none; }
- .table { width: 100%; border-collapse: collapse; border-spacing: 0; position: relative; z-index: 1; min-width: 600px; }
- .table th, .table td { padding: 0.8rem 1rem; text-align: left; border-bottom: var(--border-width) var(--border-style) var(--border-color); border-right: 1px dashed rgba(0,0,0,0.1); white-space: nowrap; vertical-align: middle; }
- .table th:last-child, .table td:last-child { border-right: none; }
- .table thead th { background-color: var(--primary); color: var(--dark); text-transform: uppercase; letter-spacing: 1px; font-weight: bold; border-top: none; border-bottom-width: var(--border-width); position: sticky; top: -1px; z-index: 2; }
- .table tbody tr:last-child td { border-bottom: none; }
- .table tbody tr:hover { background-color: rgba(255, 178, 107, 0.2); }
- .table tfoot td { border-top: var(--border); font-weight: bold; background-color: rgba(255, 255, 255, 0.5); position: sticky; bottom: -1px; z-index: 2; }
- .table .wrap-text { white-space: normal; }
- .table .avatar { width: 30px; height: 30px; font-size: 0.9rem; margin-right: 0.5rem; }
+.progress-text {
+ position: absolute;
+ inset: 0;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ color: var(--dark);
+ font-weight: bold;
+ z-index: 1;
+ text-shadow: 1px 1px 0px rgba(255, 255, 255, 0.7);
+ font-size: 0.9rem;
+ white-space: nowrap;
+}
- /* Utilities */
- .mb-1 { margin-bottom: 0.5rem !important; } .mb-2 { margin-bottom: 1rem !important; } .mb-3 { margin-bottom: 1.5rem !important; } .mb-4 { margin-bottom: 2rem !important; }
- .mt-1 { margin-top: 0.5rem !important; } .mt-2 { margin-top: 1rem !important; } .mt-3 { margin-top: 1.5rem !important; } .mt-4 { margin-top: 2rem !important; }
- .ml-1 { margin-left: 0.5rem !important; } .ml-2 { margin-left: 1rem !important; }
- .mr-1 { margin-right: 0.5rem !important; } .mr-2 { margin-right: 1rem !important; }
- .text-center { text-align: center; } .text-right { text-align: right; }
- .flex { display: flex; } .justify-between { justify-content: space-between; } .justify-end { justify-content: flex-end; } .justify-center { justify-content: center; } .items-center { align-items: center; }
- .flex-wrap { flex-wrap: wrap; } .flex-nowrap { flex-wrap: nowrap; }
- .flex-grow { flex-grow: 1; } .flex-shrink-0 { flex-shrink: 0; } .w-full { width: 100%; }
+/* Toggle Switch - Refined */
+.switch-container {
+ position: relative;
+ display: inline-block;
+ width: 64px;
+ /* Slightly smaller */
+ height: 34px;
+ /* Slightly smaller */
+ margin-bottom: 1rem;
+ vertical-align: middle;
+}
- /* Tooltip */
- .tooltip { position: relative; display: inline-block; }
- .tooltip-trigger { cursor: help; border-bottom: 1px dashed var(--dark); }
- .btn.tooltip-trigger { border-bottom: none; }
- .tooltip-text {
- visibility: hidden; opacity: 0;
- min-width: 150px; max-width: 250px;
- background-color: var(--dark); color: var(--light);
- text-align: center;
- border: 2px solid var(--black); padding: 0.75rem;
- position: absolute;
- z-index: 1500; /* Increased Z-index significantly */
- bottom: 130%; left: 50%;
- transform: translateX(-50%) scale(0.95);
- transform-origin: bottom center;
- transition: opacity var(--transition-speed) var(--transition-ease-out),
- visibility 0s linear var(--transition-speed),
- transform var(--transition-speed) var(--transition-ease-out);
- box-shadow: var(--shadow-md);
- font-size: 0.9rem; line-height: 1.4;
- pointer-events: none;
- }
- /* NOTE on Tooltip Clipping: Tooltips use position:absolute and high z-index.
+.switch-container input {
+ position: absolute;
+ opacity: 0;
+ width: 100%;
+ height: 100%;
+ top: 0;
+ left: 0;
+ margin: 0;
+ cursor: pointer;
+ z-index: 2;
+}
+
+.switch {
+ position: absolute;
+ cursor: pointer;
+ inset: 0;
+ background-color: var(--light);
+ border: var(--border);
+ /* box-shadow: var(--shadow-inset), var(--shadow-sm); REMOVED - potential conflict */
+ box-shadow: var(--shadow-inset);
+ /* Keep inset shadow only */
+ transition: background-color 0.4s var(--transition-ease-out);
+ pointer-events: none;
+ z-index: 1;
+}
+
+.switch:before {
+ position: absolute;
+ content: "";
+ height: 24px;
+ /* Adjusted size */
+ width: 24px;
+ /* Adjusted size */
+ left: 2px;
+ /* Adjusted position */
+ top: 50%;
+ /* Center vertically */
+ background-color: var(--dark);
+ border: 2px solid var(--light);
+ box-shadow: var(--shadow-sm);
+ transition: transform 0.4s var(--transition-ease-out),
+ background-color 0.4s var(--transition-ease-out),
+ border-color 0.4s var(--transition-ease-out);
+ transform: translateY(-50%);
+ /* Vertical centering */
+}
+
+.switch-container input:checked+.switch {
+ background-color: var(--secondary-accent);
+}
+
+.switch-container input:checked+.switch:before {
+ background-color: var(--light);
+ border-color: var(--dark);
+ /* Width (64) - border*2 (6) - left (2) - width (24) = 32 */
+ transform: translate(30px, -50%);
+ /* Adjusted translation */
+}
+
+/* Tables */
+.table-container {
+ overflow-x: auto;
+ margin-bottom: 1.5rem;
+ border: var(--border);
+ box-shadow: var(--shadow-md);
+ background-color: var(--light);
+ position: relative;
+ /* overflow: hidden; */
+ /* Can clip tooltips */
+}
+
+.table-container::before {
+ content: "";
+ position: absolute;
+ inset: 0;
+ background-image: var(--paper-texture);
+ opacity: 0.6;
+ z-index: 0;
+ pointer-events: none;
+}
+
+.table {
+ width: 100%;
+ border-collapse: collapse;
+ border-spacing: 0;
+ position: relative;
+ z-index: 1;
+ min-width: 600px;
+}
+
+.table th,
+.table td {
+ padding: 0.8rem 1rem;
+ text-align: left;
+ border-bottom: var(--border-width) var(--border-style) var(--border-color);
+ border-right: 1px dashed rgba(0, 0, 0, 0.1);
+ white-space: nowrap;
+ vertical-align: middle;
+}
+
+.table th:last-child,
+.table td:last-child {
+ border-right: none;
+}
+
+.table thead th {
+ background-color: var(--primary);
+ color: var(--dark);
+ text-transform: uppercase;
+ letter-spacing: 1px;
+ font-weight: bold;
+ border-top: none;
+ border-bottom-width: var(--border-width);
+ position: sticky;
+ top: -1px;
+ z-index: 2;
+}
+
+.table tbody tr:last-child td {
+ border-bottom: none;
+}
+
+.table tbody tr:hover {
+ background-color: rgba(255, 178, 107, 0.2);
+}
+
+.table tfoot td {
+ border-top: var(--border);
+ font-weight: bold;
+ background-color: rgba(255, 255, 255, 0.5);
+ position: sticky;
+ bottom: -1px;
+ z-index: 2;
+}
+
+.table .wrap-text {
+ white-space: normal;
+}
+
+.table .avatar {
+ width: 30px;
+ height: 30px;
+ font-size: 0.9rem;
+ margin-right: 0.5rem;
+}
+
+/* Utilities */
+.mb-1 {
+ margin-bottom: 0.5rem !important;
+}
+
+.mb-2 {
+ margin-bottom: 1rem !important;
+}
+
+.mb-3 {
+ margin-bottom: 1.5rem !important;
+}
+
+.mb-4 {
+ margin-bottom: 2rem !important;
+}
+
+.mt-1 {
+ margin-top: 0.5rem !important;
+}
+
+.mt-2 {
+ margin-top: 1rem !important;
+}
+
+.mt-3 {
+ margin-top: 1.5rem !important;
+}
+
+.mt-4 {
+ margin-top: 2rem !important;
+}
+
+.ml-1 {
+ margin-left: 0.5rem !important;
+}
+
+.ml-2 {
+ margin-left: 1rem !important;
+}
+
+.mr-1 {
+ margin-right: 0.5rem !important;
+}
+
+.mr-2 {
+ margin-right: 1rem !important;
+}
+
+.text-center {
+ text-align: center;
+}
+
+.text-right {
+ text-align: right;
+}
+
+.flex {
+ display: flex;
+}
+
+.justify-between {
+ justify-content: space-between;
+}
+
+.justify-end {
+ justify-content: flex-end;
+}
+
+.justify-center {
+ justify-content: center;
+}
+
+.items-center {
+ align-items: center;
+}
+
+.flex-wrap {
+ flex-wrap: wrap;
+}
+
+.flex-nowrap {
+ flex-wrap: nowrap;
+}
+
+.flex-grow {
+ flex-grow: 1;
+}
+
+.flex-shrink-0 {
+ flex-shrink: 0;
+}
+
+.w-full {
+ width: 100%;
+}
+
+/* Tooltip */
+.tooltip {
+ position: relative;
+ display: inline-block;
+}
+
+.tooltip-trigger {
+ cursor: help;
+ border-bottom: 1px dashed var(--dark);
+}
+
+.btn.tooltip-trigger {
+ border-bottom: none;
+}
+
+.tooltip-text {
+ visibility: hidden;
+ opacity: 0;
+ min-width: 150px;
+ max-width: 250px;
+ background-color: var(--dark);
+ color: var(--light);
+ text-align: center;
+ border: 2px solid var(--black);
+ padding: 0.75rem;
+ position: absolute;
+ z-index: 1500;
+ /* Increased Z-index significantly */
+ bottom: 130%;
+ left: 50%;
+ transform: translateX(-50%) scale(0.95);
+ transform-origin: bottom center;
+ transition: opacity var(--transition-speed) var(--transition-ease-out),
+ visibility 0s linear var(--transition-speed),
+ transform var(--transition-speed) var(--transition-ease-out);
+ box-shadow: var(--shadow-md);
+ font-size: 0.9rem;
+ line-height: 1.4;
+ pointer-events: none;
+}
+
+/* NOTE on Tooltip Clipping: Tooltips use position:absolute and high z-index.
However, if a PARENT element (like .card, .modal-container, .table-container)
has `overflow: hidden` or `overflow: auto/scroll`, the tooltip WILL BE CLIPPED
by that parent's boundaries, regardless of z-index.
The most reliable fix involves JavaScript to append the tooltip to the document body
when shown, removing it from the parent's clipping context.
This CSS provides structure but cannot overcome parent overflow clipping. */
- .tooltip-text::after { content: ""; position: absolute; top: 100%; left: 50%; margin-left: -8px; border-width: 8px; border-style: solid; border-color: var(--dark) transparent transparent transparent; }
- .tooltip .tooltip-trigger:hover + .tooltip-text,
- .tooltip .tooltip-trigger:focus-visible + .tooltip-text,
- .tooltip-text.visible {
- visibility: visible; opacity: 1;
- transform: translateX(-50%) scale(1);
- transition-delay: 0s, 0s, 0s;
- }
+.tooltip-text::after {
+ content: "";
+ position: absolute;
+ top: 100%;
+ left: 50%;
+ margin-left: -8px;
+ border-width: 8px;
+ border-style: solid;
+ border-color: var(--dark) transparent transparent transparent;
+}
- /* Spinner - Pulsing Dots */
- .spinner-dots {
- display: inline-flex; /* Use flex for alignment */
- align-items: center; /* Vertically center dots */
- justify-content: center;
- width: auto; /* Adjust width based on content */
- height: 50px; /* Match old spinner height or adjust */
- }
- .spinner-dots span {
- display: inline-block;
- width: 12px;
- height: 12px;
- margin: 0 4px; /* Spacing between dots */
- background-color: var(--primary);
- border-radius: 50%;
- box-shadow: var(--shadow-sm);
- animation: pulse-dot 1.2s infinite ease-in-out both;
- }
- .spinner-dots span:nth-child(1) { animation-delay: -0.32s; }
- .spinner-dots span:nth-child(2) { animation-delay: -0.16s; }
- .spinner-dots span:nth-child(3) { animation-delay: 0s; }
+.tooltip .tooltip-trigger:hover+.tooltip-text,
+.tooltip .tooltip-trigger:focus-visible+.tooltip-text,
+.tooltip-text.visible {
+ visibility: visible;
+ opacity: 1;
+ transform: translateX(-50%) scale(1);
+ transition-delay: 0s, 0s, 0s;
+}
- @keyframes pulse-dot {
- 0%, 80%, 100% { transform: scale(0.8); opacity: 0.5; }
- 40% { transform: scale(1.1); opacity: 1; }
- }
+/* Spinner - Pulsing Dots */
+.spinner-dots {
+ display: inline-flex;
+ /* Use flex for alignment */
+ align-items: center;
+ /* Vertically center dots */
+ justify-content: center;
+ width: auto;
+ /* Adjust width based on content */
+ height: 50px;
+ /* Match old spinner height or adjust */
+}
- /* Small spinner dots */
- .spinner-dots-sm { height: 30px; } /* Adjust height */
- .spinner-dots-sm span { width: 8px; height: 8px; margin: 0 3px; box-shadow: var(--shadow-sm); }
+.spinner-dots span {
+ display: inline-block;
+ width: 12px;
+ height: 12px;
+ margin: 0 4px;
+ /* Spacing between dots */
+ background-color: var(--primary);
+ border-radius: 50%;
+ box-shadow: var(--shadow-sm);
+ animation: pulse-dot 1.2s infinite ease-in-out both;
+}
- .btn .spinner-dots-sm { height: auto; vertical-align: middle; margin: 0 0.5em; } /* Spinner inside button */
- .btn .spinner-dots-sm span { background-color: currentColor; } /* Match button text color */
+.spinner-dots span:nth-child(1) {
+ animation-delay: -0.32s;
+}
+
+.spinner-dots span:nth-child(2) {
+ animation-delay: -0.16s;
+}
+
+.spinner-dots span:nth-child(3) {
+ animation-delay: 0s;
+}
+
+@keyframes pulse-dot {
+
+ 0%,
+ 80%,
+ 100% {
+ transform: scale(0.8);
+ opacity: 0.5;
+ }
+
+ 40% {
+ transform: scale(1.1);
+ opacity: 1;
+ }
+}
+
+/* Small spinner dots */
+.spinner-dots-sm {
+ height: 30px;
+}
+
+/* Adjust height */
+.spinner-dots-sm span {
+ width: 8px;
+ height: 8px;
+ margin: 0 3px;
+ box-shadow: var(--shadow-sm);
+}
+
+.btn .spinner-dots-sm {
+ height: auto;
+ vertical-align: middle;
+ margin: 0 0.5em;
+}
+
+/* Spinner inside button */
+.btn .spinner-dots-sm span {
+ background-color: currentColor;
+}
+
+/* Match button text color */
- /* Responsive */
- @media (max-width: 768px) {
- body { padding: 1rem; font-size: 1rem; }
- .card, .modal-container, .tab-content { padding: 1rem; }
- .card-header, .card-footer, .modal-header, .modal-footer { padding: 0.75rem 1rem; margin-left: -1rem; margin-right: -1rem; }
- .card-header { margin-top: -1rem; margin-bottom: 1rem; }
- .card-footer { margin-bottom: -1rem; margin-top: 1rem; }
- .modal-header { margin-top: -1rem; margin-bottom: 1rem; }
- .modal-footer { margin-bottom: -1rem; margin-top: 1rem; }
- .modal-footer .btn { margin: 0.25rem; }
+/* Responsive */
+@media (max-width: 768px) {
+ body {
+ padding: 1rem;
+ font-size: 1rem;
+ }
- /* Tabs on mobile */
- .tab-list { margin-bottom: -3px; /* Adjust for border width */ }
- .tab-item { flex-grow: 1; margin-right: 0; text-align: center; border-left: none; border-right: none; border-bottom-width: var(--border-width); }
- .tab-item:not(:last-child) { border-right: var(--border); }
- .tab-item[aria-selected="true"] { border-bottom-color: var(--primary); margin-bottom: 0; /* No longer needs negative margin */ z-index: 2; }
- .tab-content { margin-top: -3px; }
+ .card,
+ .modal-container,
+ .tab-content {
+ padding: 1rem;
+ }
- /* List items on mobile */
- .list-item-content { flex-direction: column; align-items: flex-start; }
- .list-item-main { margin-right: 0; width: 100%; margin-bottom: 0.5rem;}
- .list-item-details { margin-left: 0; margin-top: 0.5rem; flex-wrap: wrap; /* Allow badges/avatar wrap on mobile */ }
- .list-item-details > * { margin-left: 0; margin-right: 0.5rem; margin-bottom: 0.25rem; } /* Adjust spacing for wrap */
- .list-item-actions { /* Non-swipe actions */
- width: 100%;
- justify-content: flex-end;
- margin-top: 0.5rem;
- padding-left: 0;
- }
- /* Adjust swipe reveal distance if needed for mobile */
- .list-item.is-swiped .list-item-content { transform: translateX(-120px); } /* Example smaller distance */
+ .card-header,
+ .card-footer,
+ .modal-header,
+ .modal-footer {
+ padding: 0.75rem 1rem;
+ margin-left: -1rem;
+ margin-right: -1rem;
+ }
+
+ .card-header {
+ margin-top: -1rem;
+ margin-bottom: 1rem;
+ }
+
+ .card-footer {
+ margin-bottom: -1rem;
+ margin-top: 1rem;
+ }
+
+ .modal-header {
+ margin-top: -1rem;
+ margin-bottom: 1rem;
+ }
+
+ .modal-footer {
+ margin-bottom: -1rem;
+ margin-top: 1rem;
+ }
+
+ .modal-footer .btn {
+ margin: 0.25rem;
+ }
+
+ /* Tabs on mobile */
+ .tab-list {
+ margin-bottom: -3px;
+ /* Adjust for border width */
+ }
+
+ .tab-item {
+ flex-grow: 1;
+ margin-right: 0;
+ text-align: center;
+ border-left: none;
+ border-right: none;
+ border-bottom-width: var(--border-width);
+ }
+
+ .tab-item:not(:last-child) {
+ border-right: var(--border);
+ }
+
+ .tab-item[aria-selected="true"] {
+ border-bottom-color: var(--primary);
+ margin-bottom: 0;
+ /* No longer needs negative margin */
+ z-index: 2;
+ }
+
+ .tab-content {
+ margin-top: -3px;
+ }
+
+ /* List items on mobile */
+ .list-item-content {
+ flex-direction: column;
+ align-items: flex-start;
+ }
+
+ .list-item-main {
+ margin-right: 0;
+ width: 100%;
+ margin-bottom: 0.5rem;
+ }
+
+ .list-item-details {
+ margin-left: 0;
+ margin-top: 0.5rem;
+ flex-wrap: wrap;
+ /* Allow badges/avatar wrap on mobile */
+ }
+
+ .list-item-details>* {
+ margin-left: 0;
+ margin-right: 0.5rem;
+ margin-bottom: 0.25rem;
+ }
+
+ /* Adjust spacing for wrap */
+ .list-item-actions {
+ /* Non-swipe actions */
+ width: 100%;
+ justify-content: flex-end;
+ margin-top: 0.5rem;
+ padding-left: 0;
+ }
+
+ /* Adjust swipe reveal distance if needed for mobile */
+ .list-item.is-swiped .list-item-content {
+ transform: translateX(-120px);
+ }
+
+ /* Example smaller distance */
- .table { min-width: unset; }
- .table thead th { top: -1px; } .table tfoot td { bottom: -1px; }
- .table th, .table td { padding: 0.6rem 0.5rem; font-size: 0.9rem; white-space: normal; }
+ .table {
+ min-width: unset;
+ }
- .flex-layout-stack-mobile { flex-direction: column; }
- .flex-layout-stack-mobile > .card { width: 100% !important; margin: 0 0 1.5rem 0 !important; flex-basis: auto !important; }
- .form-row-wrap-mobile { flex-direction: column; }
- .form-row-wrap-mobile > .form-group { margin-right: 0 !important; width: 100%; }
- .form-row-wrap-mobile > .form-group:not(:last-child) { margin-bottom: 1.5rem; }
- }
+ .table thead th {
+ top: -1px;
+ }
+
+ .table tfoot td {
+ bottom: -1px;
+ }
+
+ .table th,
+ .table td {
+ padding: 0.6rem 0.5rem;
+ font-size: 0.9rem;
+ white-space: normal;
+ }
+
+ .flex-layout-stack-mobile {
+ flex-direction: column;
+ }
+
+ .flex-layout-stack-mobile>.card {
+ width: 100% !important;
+ margin: 0 0 1.5rem 0 !important;
+ flex-basis: auto !important;
+ }
+
+ .form-row-wrap-mobile {
+ flex-direction: column;
+ }
+
+ .form-row-wrap-mobile>.form-group {
+ margin-right: 0 !important;
+ width: 100%;
+ }
+
+ .form-row-wrap-mobile>.form-group:not(:last-child) {
+ margin-bottom: 1.5rem;
+ }
+}
\ No newline at end of file
diff --git a/fe/src/components/ConflictResolutionDialog.vue b/fe/src/components/ConflictResolutionDialog.vue
index a847ba5..aa187bb 100644
--- a/fe/src/components/ConflictResolutionDialog.vue
+++ b/fe/src/components/ConflictResolutionDialog.vue
@@ -40,7 +40,7 @@
{{ formatKey(key) }}
{{ formatValue(value)
- }}
+ }}
@@ -59,7 +59,7 @@
{{ formatKey(key) }}
{{ formatValue(value)
- }}
+ }}
diff --git a/fe/src/components/CreateListModal.vue b/fe/src/components/CreateListModal.vue
index 310d413..835beb4 100644
--- a/fe/src/components/CreateListModal.vue
+++ b/fe/src/components/CreateListModal.vue
@@ -57,7 +57,7 @@ const props = defineProps<{
const emit = defineEmits<{
(e: 'update:modelValue', value: boolean): void;
- (e: 'created'): void;
+ (e: 'created', newList: any): void;
}>();
const isOpen = useVModel(props, 'modelValue', emit);
@@ -108,7 +108,7 @@ const onSubmit = async () => {
}
loading.value = true;
try {
- await apiClient.post(API_ENDPOINTS.LISTS.BASE, {
+ const response = await apiClient.post(API_ENDPOINTS.LISTS.BASE, {
name: listName.value,
description: description.value,
group_id: selectedGroupId.value,
@@ -116,7 +116,7 @@ const onSubmit = async () => {
notificationStore.addNotification({ message: 'List created successfully', type: 'success' });
- emit('created');
+ emit('created', response.data);
closeModal();
} catch (error: unknown) {
const message = error instanceof Error ? error.message : 'Failed to create list';
diff --git a/fe/src/layouts/MainLayout.vue b/fe/src/layouts/MainLayout.vue
index 7244065..81fb24e 100644
--- a/fe/src/layouts/MainLayout.vue
+++ b/fe/src/layouts/MainLayout.vue
@@ -5,7 +5,11 @@